Android listview指定垂直滑動距離

在寫自動化代碼的時候對於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,可以比較靈活的實現滾動操作(例如滾動一屏或者半屏)。


發佈了7 篇原創文章 · 獲贊 60 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章