在之前的控件搜索原理解析的文章中提到了,robotium在搜索控件时具有自动滚动的功能,接着就来了解一下其滚动是怎么实现的。滚动的功能实现在主要在Scroller.java中(吐槽一下,为什么Robotium的类名都起的清晰易懂,而代码里的变量名则经常文不对题呢??),主要入口是public boolean scroll(int direction, boolean allTheWay),里面会根据所需滚动的View类型——ListView, ScrollView以及WebView,分别采取三种不同的操作, 本文先了解一下ListView的滚动。
AbsListView的滚动
滚动原理很简单,直接利用view.setSelection(int positon)(不用担心会触发点击事件,查看ListView或GridView API文档的说明,其中有这样一句, If in touch mode, the item will not be selected but it will still be positioned appropriately. )
不过虽然结果很简单,但过程还是有些曲折的,接着看public <T extends AbsListView> boolean scrollList(T absListView, int direction, boolean allTheWay) 这个函数,以向下为例,跟踪一下滚动流程。
public <T extends AbsListView> boolean scrollList(T absListView, int direction, boolean allTheWay) { if(absListView == null){ return false; } if (direction == DOWN) { //向下滚动 if (allTheWay) { //allTheWay表示直接滚到底 scrollListToLine(absListView, absListView.getCount()-1); return false; } if (absListView.getLastVisiblePosition() >= absListView.getCount()-1) { //列表已经处在底部 scrollListToLine(absListView, absListView.getLastVisiblePosition()); return false; } if(absListView.getFirstVisiblePosition() != absListView.getLastVisiblePosition()) //列表的显示宽度大于1 scrollListToLine(absListView, absListView.getLastVisiblePosition()); else //列表的显示宽度等于1,则要滚动至FirstVisiblePosition()+1 scrollListToLine(absListView, absListView.getFirstVisiblePosition()+1); } else if (direction == UP) { if (allTheWay || absListView.getFirstVisiblePosition() < 2) { //allTheWay或列表长度小于2,则直接滚到顶部 scrollListToLine(absListView, 0); return false; } //计算列表的显示宽度 final int lines = absListView.getLastVisiblePosition() - absListView.getFirstVisiblePosition(); //根据宽度计算出该滚动至第几行 int lineToScrollTo = absListView.getFirstVisiblePosition() - lines; if(lineToScrollTo == absListView.getLastVisiblePosition()) //当显示宽度为1时,向上回滚一行即可 lineToScrollTo--; if(lineToScrollTo < 0) //当上面的隐藏行数小于显示宽度时,直接滚动至第一行即可 lineToScrollTo = 0; scrollListToLine(absListView, lineToScrollTo); } sleeper.sleep(); return true; } public <T extends AbsListView> void scrollListToLine(final T view, final int line){ if(view == null) Assert.fail("AbsListView is null!"); final int lineToMoveTo; if(view instanceof GridView) //如果是GridView的话再+1 //当向下滚动时,如果只滚动至latsVisiblePositon,显然会重复显示一个元素, //而且当postion > GridView.getCount - 1时,调用gridView.setSelection,gridView直接滚动到底部。 lineToMoveTo = line+1; else lineToMoveTo = line; inst.runOnMainSync(new Runnable(){ public void run(){ //通过setSelection完成列表的自动滚动。 view.setSelection(lineToMoveTo); } });
对ListView比较了解的话,这里的代码应该很简单。不过有一个地方不明白,就是scrollListToLine对GridView的lineToMoveTo加了一。目前经过查看API文档和自己做得实验,找到+1的理由只有如下两点:
1) 当方向向下且列表显示宽度大于1时,加1可以避免lastVisiblePositon元素的重复显示
2) 当postion > view.size() – 1时,setSelection(postion) 会导致listView会滚动至顶部,而GridView会滚动至底部。
所以当滚动方向向下且列表宽度超过1时,此GridView的+1是能正常工作的。
不过,在如下情况下这个+1应该是会出错的:
1) 当方向向下且列表宽度为1时,此时在第一层searchFor时已经加了1,而scrollListToLine这里再给GridView加了1,那么如果原本的lastVisiblePosition为26的话,经过这样处理,会直接滚动到28,而27行就被直接跳过了(经过亲自验证,此时确实会出现问题)。
2) 方向向上时,这个+1就更加无厘头了,例如当用Solo.scrollToTop()时,gridView会滚到position = 1;更例如当列表宽度为1时,调用Solo.scrollUp(),你会发现gridView在原地踏步(两条都验证完毕)。
ScrollView的滚动
相对比AbsListView,ScrollView的滚动就简单多了,直接上代码
private boolean scrollScrollView(final ScrollView view, int direction){ if(view == null){ return false; } //获取控件高度 int height = view.getHeight(); //滚动量减一,为了容错性? height--; int scrollTo = -1; //向下滚动,滚动量为正值 if (direction == DOWN) { scrollTo = height; } //向下滚动,滚动量为负 else if (direction == UP) { scrollTo = -height; } //记录当前控件处于滚动框顶部的位置 int originalY = view.getScrollY(); final int scrollAmount = scrollTo; inst.runOnMainSync(new Runnable(){ public void run(){ //滚动 view.scrollBy(0, scrollAmount); } }); //对比滚动前后的位置,如果一样,说明已到达底部,返回false,否则返回true if (originalY == view.getScrollY()) { return false; } else{ return true; } }
WebView的滚动
更加简单,不多说了
public boolean scrollWebView(final WebView webView, int direction, final boolean allTheWay){ //滚动webView时,直接调用webView.pageDown()或 //webView.pageUp() if (direction == DOWN) { inst.runOnMainSync(new Runnable(){ public void run(){ canScroll = webView.pageDown(allTheWay); } }); } if(direction == UP){ inst.runOnMainSync(new Runnable(){ public void run(){ canScroll = webView.pageUp(allTheWay); } }); } return canScroll; }
相关推荐
robotium 5.0.1 源码 直接将源码包含进测试项目中使用,不用加载jar包,或者直接自定义更改源码适应指定要求。
robotium 最新版本5.0.1 robotium-solo-5.0.1.jar
这是spring5.0.1的源码包,不是spring的依赖jar包,请务必不要直接放到项目中
ExtJs5.0.1官方源码,方便找不到历史版本代码的同学。
骑士cms(74CMS)高效人才招聘系统 v5.0.1 正式版 更新日志 新增:后台增加跳转页面 新增:短信预警提醒,方便客户及时充值 新增:企业与个人账号通用 新增:未付费且登录的企业单独呈现,方便追踪客户 新增:...
android 5.0.1 源码
PotaPoco 5.0.1最新版源码。 如:Insert时返回的不是true,而是1了。
I函数简介获取变量如果要获取的变量类型是 get、post 或 put,可以统一用 param 变量类型,param 变量类型是框架特有的支持自动判断当前请求类
ffmpeg-5.0.1
robotium 最新版本5.0.1 robotium-solo-5.0.1.jar
android5.0.1-api21 官网源码
Net实战商用源码---最新TourEx旅游系统v5.0.1多城市版源码 旅游网源码。
elasticsearch5.0.1源码中elasticsearch-5.0.1\core\src\main文件中的源码,已通过gradle工具转换到了eclipse可以直接打开的工程
骑士cms人才系统是一项基于PHP+MYSQL为核心开发的一套 + 开源专业人才招聘系统。软件具执行效率高、模板自由切换、后台管理功能方便等诸多优秀特点。全部代码都为骑士网络原创
LoraWAN V5.0.1版本源码。有需要的朋友可以下载研究研究。
VNC-5.0.1.rar VNC-5.0.1.rar VNC-5.0.1.rar VNC-5.0.1.rar
Elasticsearch-5.0.1-src源码 CSDN下载会快很多!
Hp-Socket For E 5.0.1 beta1 源码+模块+例程帮助文档,较全面的,有需要的下载吧,自己用易语言开发用到的
ACDSee5.0.1精简美化
robotium-solo-3.4.1.jar,