Robotium 5.0.1 源码解析之滚动原理
来源:互联网 发布:环比数据分析报告 编辑:程序博客网 时间:2024/06/07 18:15
Robotium 5.0.1 源码解析之滚动原理
- 转自:http://stream-town.iteye.com/blog/2025306
在之前的控件搜索原理解析的文章中提到了,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 源码解析之滚动原理
- Robotium 5.0.1 源码解析之控件搜索
- Robotium 5.0.1 源码解析之控件搜索
- Robotium 5.0.1 源码解析之控件搜索
- Robotium 5.0.1 源码解析之控件搜索
- Robotium源码分析之运行原理
- Robotium源码分析之运行原理
- Robotium源码分析之运行原理
- Robotium源码分析之运行原理
- Robotium-5.0.1-源代码解析(1)---ActivityUtils
- Robotium框架的使用和源码解析
- hive源码解析之运行原理
- delayQueue原理理解之源码解析
- Android源码解析之LayoutInflater原理
- Vue-lazyload原理详解之源码解析
- robotium原理之获取WebElement元素
- robotium原理之获取WebElement元素
- Robotium源码分析之Instrumentation进阶
- 边缘检测
- 正则表达式之 贪婪与非贪婪模式详解(概述)
- Android基础笔记(十一)- Service基础和注意事项以及Activity与Service的通信
- spring 中四种注解@controller,@service,@repository,@component的区别
- servlet基础梳理(二)
- Robotium 5.0.1 源码解析之滚动原理
- 【黑马程序员】iOS学习之路——C语言之数据的基本运算
- Access中保留关键字汇总
- UVA - 557 Burger
- Robotium 5.0.1 源码解析之控件搜索
- 【LeetCode】Excel Sheet Column Title
- 新的开始
- android意图传参返回结果(六)
- ios-day12-03(ios开发中数据存储之偏好设置(Preference))