首頁 > 軟體

Android拖拽助手ViewDragHelper的建立與使用範例

2022-05-19 19:02:09

前言

在專案中,我們經常自定義ViewGroup,有時候需要拖拽它的子View,讓其運動,一般情況下如果我們手動處理各種滑動事件,非常麻煩,谷歌給我們提供了一個輔助類ViewDragHelper,ViewDragHelper給我們提供了很多拖拽相關的方法以及狀態跟蹤。

建立範例

ViewDragHelper.create(vp, callback);

ViewDragHelper的建立比較簡單,它的建構函式是私有的,只能通過create()方法建立,第一個引數是一個ViewGroup,也就是需要使用ViewDragHelper的自定義View,第二個引數callback,提供了很多拖拽相關的回撥。

ViewDragHelper.Callback

下面是幾個常用的方法

private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
   public boolean tryCaptureView(View child, int pointerId)
   public int getViewHorizontalDragRange(View child)
   public int clampViewPositionHorizontal(View child, int left, int dx)
   public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) 
   public void onViewReleased(View releasedChild, float xvel, float yvel) 
  • tryCaptureView返回一個boolean,使用者判斷是否捕獲當前view的觸控事件
  • getViewHorizontalDragRange獲取child水平方向的拖拽範圍
  • clampViewPositionHorizontal控制child在水平方向的移動,我們可以通過dx修正left的值,返回值表示我們真正想讓child的left變成的值
  • clampViewPositionVertical和水平方向類似
  • onViewPositionChanged 當child位置改變時候的回撥
  • onViewReleased當拖拽的view釋放的時候回撥

使用

自定義一個簡單的側拉選單,該選單有兩個子View,一個主介面,一個側邊選單介面

首先自定義一個ViewGroup並初始化ViewDragHelper

public class SlideMenu extends FrameLayout{
    private void init(){
       viewDragHelper = ViewDragHelper.create(this, callback);
    }
}

然後重寫onInterceptTouchEvent和onTouchEvent,將這兩個方法的處理邏輯交給ViewDragHelper

public boolean onInterceptTouchEvent(MotionEvent ev) {
   return viewDragHelper.shouldInterceptTouchEvent(ev);
}
public boolean onTouchEvent(MotionEvent event) {
   viewDragHelper.processTouchEvent(event);
   return true;
}

實現ViewDragHelper.Callback,重寫tryCaptureView,在當前Layout中兩個子VIew都需要滑動,所以直接返回true.

public boolean tryCaptureView(View child, int pointerId) {
   return true;
}

先限制一下橫向滑動範圍,給一個最大值

public int getViewHorizontalDragRange(View child) {
   return (int) dragRange;
}

主介面在滑動過程中,我們需要控制下它在水平方向的移動距離

public int clampViewPositionHorizontal(View child, int left, int dx) {
   if(child==mainView){
      if(left<0)left=0;//限制mainView的左邊
      if(left>dragRange)left=(int) dragRange;//限制mainView的右邊
   }
   return left;
}

在滑動過程中,根據拖拽回撥重新對側拉選單和主介面佈局,不斷重新整理他們的位置資訊,這裡簡單起見,讓側拉選單固定,只是主介面滑動。

public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
   if(changedView==menuView){
      menuView.layout(0, 0, menuView.getMeasuredWidth(),menuView.getMeasuredHeight());
      int newLeft = mainView.getLeft()+dx;
      if(newLeft<0)newLeft=0;
      if(newLeft>dragRange)newLeft=(int) dragRange;mainView.layout(newLeft,mainView.getTop()+dy,newLeft+mainView.getMeasuredWidth(),mainView.getBottom()+dy);
   }
}

當手指擡起釋放view的時候,可能我們只是拖拽了一點,這時候我們需要根據當前拖拽的資訊決定是開啟選單還是關閉選單。

public void onViewReleased(View releasedChild, float xvel, float yvel) {
   if(mainView.getLeft()<dragRange/2){
      //在左半邊
      close();
   }else {
      //在右半邊
      open();
   }
}

對於view的滑動ViewDragHelper也提供了smoothSlideViewTo方法,所以close和open方法就很簡單

public void close() {
   viewDragHelper.smoothSlideViewTo(mainView,0,mainView.getTop());
   ViewCompat.postInvalidateOnAnimation(SlideMenu.this);
}
public void computeScroll() {
   if(viewDragHelper.continueSettling(true)){
      ViewCompat.postInvalidateOnAnimation(SlideMenu.this);
   }
}

然後還可以提供一些拖拽狀態回撥,比如拖拽完成,拖拽中等狀態,這些比較簡單,直接在onViewPositionChanged中處理就可以了。

最後看一下效果

總結

到此這篇關於Android拖拽助手ViewDragHelper的建立與使用的文章就介紹到這了,更多相關Android拖拽助手ViewDragHelper內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com