Android listview指定垂直滑动距离

本文介绍了一种在Android应用中实现ListView自定义垂直滚动距离的方法,通过反射调用ListView内部的trackMotionScroll方法,使得自动化测试中能够更加精确地控制ListView滚动。此方案适用于Android-10及更高版本。
摘要由CSDN通过智能技术生成

在写自动化代码的时候对于listview的拖动有时候效果不尽人意,例如robotium自带的滚动操作scrollListToLine,最终的核心就是:

inst.runOnMainSync(new Runnable(){
      public void run(){
        view.setSelection(lineToMoveTo);
      }
    });

那么也就是说这样滚动其实最终是根据listview的item高度决定滚动的距离,那么我想每次只想滚动y距离怎么做。根据android-19的AbsListView中我们会发现一个方法:

/**
  * Scrolls the list items within the view by a specified number of pixels.
  *
  * @param y the amount of pixels to scroll by vertically
  * @see #canScrollList(int)
  */
    public void scrollListBy(int y) {
     trackMotionScroll(-y, -y);
    }

实际上直接调用此方法是可以解决拖动指定listview垂直距离,但是前提是android-19(至于18有没有我不确定,17是没有的),所以通用性不强,不适合大部分平台,但是可以发现方法:

/**
  * Track a motion scroll
  *
  * @param deltaY Amount to offset mMotionView. This is the accumulated delta since the motion
  *	   began. Positive numbers mean the user's finger is moving down the screen.
  * @param incrementalDeltaY Change in deltaY from the previous event.
  * @return true if we're already at the beginning/end of the list and have nothing to do.
  */
    boolean trackMotionScroll(int deltaY, int incrementalDeltaY)
从android-10(再之前没有关注)就已经存在了,只不过是相对于包内访问的,那么接下来利用java反射即可调用这个方法,但是有一点需要注意的是因为此方法是ListView的父类的默认修饰符的方法,所以需要反射父类的方法。

/**
   * scroll Vertical
   * @param solo
   * @param y 垂直滑动的距离
   */
public void scrollVertical(final ListView listView, Activity activity, final int y){
    if(listView == null)
      return;
    activity.runOnUiThread(new Runnable() { //执行自动化测试的时候模拟滑动需要进入UI线程操作
      @Override
      public void run() {
        invokeMethod(listView, "trackMotionScroll", new Object[]{-y, -y}, new Class[]{int.class, int.class});
      }
    });
  }
  
  /**
   * 遍历当前类以及父类去查找方法,例子,写的比较简单
   * @param object 
   * @param methodName
   * @param params
   * @param paramTypes
   * @return
   */
public Object invokeMethod(Object object, String methodName, Object[] params, Class[] paramTypes){
    Object returnObj = null;
  if (object == null) {
      return null;
  }
  Class cls = object.getClass();
  Method method = null;
  for (; cls != Object.class; cls = cls.getSuperclass()) { //因为取的是父类的默认修饰符的方法,所以需要循环找到该方法
    try {
          method = cls.getDeclaredMethod(methodName, paramTypes);
          break;
        } catch (NoSuchMethodException e) {
//					e.printStackTrace();
        } catch (SecurityException e) {
//					e.printStackTrace();
        }
  }
  if(method != null){
    method.setAccessible(true);
    try {
      returnObj = method.invoke(object, params);
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      } catch (IllegalArgumentException e) {
        e.printStackTrace();
      } catch (InvocationTargetException e) {
        e.printStackTrace();
      }
  }
    return returnObj;
  }

以上就是整个比较重要的代码,若要结合robotium使用,则可以写的传参更少些:

public void scrollVertical(final ListView listView, Activity activity, final int y){
.....
}

写成:
public void scrollVertical(Solo solo, final int y){
    listViews = solo.xxx()//根据实际获取listview情况决定
    solo.getCurrentActivity().runOnUiThread(new Runnable() {
      @Override
      public void run() {
        invokeMethod(listView, "trackMotionScroll", new Object[]{-y, -y}, new Class[]{int.class, int.class});
      }
    });
  }
使用示例: 
这里指定y为动态获取设备屏幕的高度:height/n,可以比较灵活的实现滚动操作(例如滚动一屏或者半屏)。


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值