`
Stream.Town
  • 浏览: 23835 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Robotium 5.0.1 源码解析之滚动原理

阅读更多

    在之前的控件搜索原理解析的文章中提到了,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-solo-5.0.1.jar

    robotium 最新版本5.0.1 robotium-solo-5.0.1.jar

    robotium-solo-5.0.1-sources.zip

    Robotium Solo 5.0.1 版本的源码提供了深入理解其工作原理的机会,这对于开发者和测试工程师来说是极其宝贵的资源。这个压缩包文件"robotium-solo-5.0.1-sources.zip"包含了 Robotium Solo 5.0.1 版本的所有源代码,...

    spring5.0.1源码包

    虽然Spring Boot不在这个源码包中,但Spring 5.0.1源码有助于理解Spring Boot的工作原理,因为它们共享很多基础组件。 通过研究Spring 5.0.1的源码,开发者不仅可以深入理解框架的工作机制,还能学习到优秀的软件...

    ExtJs-5.0.1

    ExtJs5.0.1官方源码,方便找不到历史版本代码的同学。

    PotaPoco 5.0.1源码

    PotaPoco 5.0.1最新版源码。 如:Insert时返回的不是true,而是1了。

    ffmpeg-5.0.1

    FFmpeg的强大之处在于其灵活性和可扩展性,用户可以根据需求自定义参数,实现复杂的多媒体处理任务。同时,FFmpeg还广泛应用于服务器端的直播系统、视频处理软件以及自动化脚本中,是多媒体处理领域不可或缺的工具。

    robotium-solo-5.2.1.jar

    robotium 最新版本5.0.1 robotium-solo-5.0.1.jar

    android5.0.1-api21 官网源码

    《深入解析Android 5.0.1 (API 21) 源码》 Android 5.0.1 (API 21) 是Google在2014年底推出的一个重要版本,它带来了诸多新特性、性能优化以及用户体验的提升。这次更新不仅涉及系统的底层框架,还对用户界面和应用...

    android-5.0.1-sources

    《深入剖析Android 5.0.1源码》 Android 5.0.1,代号Lollipop,是Google发布的一个重要版本,它带来了许多重大更新和改进,为开发者提供了更多的控制和优化空间。这份"android-5.0.1-sources"包含了Android操作系统...

    Elasticsearch-5.0.1-src源码

    Elasticsearch是一款开源的全文搜索引擎,它以其高效、可扩展性以及...通过对Elasticsearch 5.0.1源码的深入研究,开发者不仅可以理解其工作原理,还能根据需求进行定制化开发,提升搜索和分析解决方案的效率和质量。

    74CMS_v5.0.1后台RCE分析1

    【74CMS_v5.0.1后台RCE分析】主要涉及的是74CMS内容管理系统的一个远程代码执行(Remote Code Execution, RCE)漏洞。这个漏洞发生在系统的后台管理部分,需要用户具有管理员权限才能利用。漏洞的触发点在于系统允许...

    74cms 骑士人才系统 v5.0.1 正式版

    总的来说,74cms骑士人才系统v5.0.1正式版是一个功能完备、易于定制的人才招聘解决方案,适用于各类企业。通过其高效的执行、丰富的功能和灵活的设计,企业能够更好地管理和运营自己的招聘流程,吸引并留住优秀的...

    ACDSee5.0.1精简美化

    《ACDSee5.0.1精简美化:探索图像管理与编辑的新维度》 ACDSee是一款历史悠久且广受欢迎的图像查看、管理和编辑软件,其5.0.1版本在用户界面和功能上进行了精心的精简和美化,旨在为用户提供更为高效且愉悦的图像...

    VNC-5.0.1.rar

    VNC-5.0.1.rar VNC-5.0.1.rar VNC-5.0.1.rar VNC-5.0.1.rar

    Net实战商用源码---最新TourEx旅游系统v5.0.1多城市版源码 旅游网源码.rar

    【Net实战商用源码---最新TourEx旅游系统v5.0.1多城市版源码 旅游网源码.rar】这个压缩包文件包含了基于.Net技术开发的TourEx旅游系统的一个完整版本,主要用于构建多城市版的在线旅游服务平台。在深入探讨这个系统...

    robotium-solo-3.4.1.jar

    robotium-solo-3.4.1.jar,

    loraWAN网关源码V5.0.1

    源码中会包含网关的配置、初始化、数据包解析、传输以及与其他网络组件交互的代码。可能还包括错误处理和日志记录功能。 3. **多通道操作**:LoRaWAN允许网关同时监听多个频率,以提高网络容量。在V5.0.1中,源码...

    phpyun_v5.0.1.beta.0703_云人才系统_求职_PHPYun_beta_phpyunv5.0.1_

    《PHPYun_v5.0.1 Beta版:云人才系统的深度解析》 PHPYun_v5.0.1.beta.0703,作为一款备受瞩目的云人才系统,旨在为求职者与雇主提供高效、便捷的人力资源管理解决方案。这款系统集成了多种功能,不仅能满足企业的...

    ACDSee 5.0.1 含注册码

    《ACDSee 5.0.1:经典图像查看与管理工具详解》 ACDSee,作为一款全球广泛使用的图像查看和管理软件,其5.0.1版本因其丰富的功能和用户友好的界面,深受广大用户的喜爱。这款软件在早期的数字图像处理领域占据了...

    spring-5.0.1jar包

    首先,Spring框架的核心特性之一是依赖注入(Dependency Injection,DI),它使得组件间的依赖关系得以解耦,增强了代码的可测试性和可维护性。在Spring 5.0.1中,依赖注入机制更加成熟,开发者可以通过注解(@...

Global site tag (gtag.js) - Google Analytics