Android拖拽輔助類ViewDragHelper的使用說明

1.先看一下如何構(gòu)造一個(gè)ViewDragHelper:

  
    public static ViewDragHelper create(@NonNull ViewGroup forParent, @NonNull ViewDragHelper.Callback cb) {
        return new ViewDragHelper(forParent.getContext(), forParent, cb);
    }

    public static ViewDragHelper create(@NonNull ViewGroup forParent, float sensitivity, @NonNull ViewDragHelper.Callback cb) {
        ViewDragHelper helper = create(forParent, cb);
        helper.mTouchSlop = (int)((float)helper.mTouchSlop * (1.0F / sensitivity));
        return helper;
    }
    
    
    
    private ViewDragHelper(@NonNull Context context, @NonNull ViewGroup forParent, @NonNull ViewDragHelper.Callback cb) {
                    //獲取觸發(fā)移動(dòng)的最小距離
            this.mTouchSlop = vc.getScaledTouchSlop();
                        //構(gòu)造OverScroller
            this.mScroller = new OverScroller(context, sInterpolator);
       
    }

ViewDragHelper的構(gòu)造是私有的,是通過create()構(gòu)造對象的阻问。

它有2個(gè)create(),第一個(gè)傳入了parent,也就是使用ViewDragHelper的View本身苍狰,第二個(gè)是Callback叽粹。然后默認(rèn)調(diào)用第二個(gè)create()蛆楞,第二個(gè)多了一個(gè)參數(shù)sensitivity也物,這個(gè)sensitivity是用來設(shè)置mTouchSlop的叛赚,它值越大mTouchSlop就會(huì)越小澡绩,就會(huì)越敏感,也就是滑動(dòng)的時(shí)候判斷move的間距越短俺附。

create()最后調(diào)用了構(gòu)造肥卡,可以在構(gòu)造方法中看到初始化了一個(gè)OverScroller,可以判斷ViewDragHelper的滑動(dòng)計(jì)算等操作也是通過OverScroller計(jì)算的(參考:Android中Scroller的使用及原理解析

2. 再看一下ViewDragHelper的Callback

 public abstract static class Callback {
        public Callback() {
        }
                //View的拖拽狀態(tài)改變時(shí)觸發(fā)
        //STATE_IDLE: 未被拖拽
        //STATE_DRAGGING:正在被拖拽
        //STATE_SETTLING: 被安放到一個(gè)位置中的狀態(tài)
        public void onViewDragStateChanged(int state) {
        }
                //拖拽時(shí)的(開始移動(dòng))觸發(fā)
        //changeView:當(dāng)前被拖拽的view
        //left:拖動(dòng)時(shí)left坐標(biāo)
        //top:拖動(dòng)時(shí)top坐標(biāo)
        //dx:拖拽時(shí)x軸偏移量
        //dy:拖拽時(shí)y軸偏移量
        public void onViewPositionChanged(@NonNull View changedView, int left, int top, @Px int dx, @Px int dy) {
        }
                //view被捕獲時(shí)觸發(fā)(也就是按下)
        //capturedChild:捕獲的view
        //activePointerId:按下手指的id,多指觸控時(shí)會(huì)用到
        //一般用于做準(zhǔn)備初始化工作
        public void onViewCaptured(@NonNull View capturedChild, int activePointerId) {
        }
                //view被放下時(shí)觸發(fā)
        //releasedChild被放下的view
        //xvel:釋放View的x軸方向上的加速度
        //yvel:釋放View的y軸方向上的加速度
        //一般用于收尾工作
        public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
        }
                //邊緣觸摸時(shí)觸發(fā)(需開啟邊緣觸摸)
        //edgeFlags:觸摸的位置EDGE_LEFT,EDGE_TOP,EDGE_RIGHT,EDGE_BOTTOM
            //pointerId: 按下手指的id,多指觸控時(shí)會(huì)用到
        //使用較少事镣,一般不重寫
        public void onEdgeTouched(int edgeFlags, int pointerId) {
        }
                //是否開啟邊緣觸摸召调,true代表開啟,默認(rèn)不開啟
        //edgeFlags:觸摸的位置EDGE_LEFT,EDGE_TOP,EDGE_RIGHT,EDGE_BOTTOM
       //使用較少蛮浑,一般不重寫
        public boolean onEdgeLock(int edgeFlags) {
            return false;
        }
                //邊緣觸摸時(shí)觸發(fā)(需開啟邊緣觸摸)
        //edgeFlags:觸摸的位置EDGE_LEFT,EDGE_TOP,EDGE_RIGHT,EDGE_BOTTOM
            //pointerId: 按下手指的id,多指觸控時(shí)會(huì)用到
        //使用較少唠叛,一般不重寫
        public void onEdgeDragStarted(int edgeFlags, int pointerId) {
        }
                //尋找當(dāng)前觸摸點(diǎn)下的子View時(shí)會(huì)調(diào)用此方法,尋找到的View會(huì)提供給tryCaptureViewForDrag()來嘗試捕獲沮稚。
        //如果需要改變子View的遍歷查詢順序可改寫此方法艺沼,例如讓下層的View優(yōu)先于上層的View被選中。
        //使用較少蕴掏,一般不重寫
        public int getOrderedChildIndex(int index) {
            return index;
        }
                //暫不明確(返回任何值都可以移動(dòng),網(wǎng)上說的都是錯(cuò)的)
       //使用較少盛杰,一般不重寫
        public int getViewHorizontalDragRange(@NonNull View child) {
            return 0;
        }
                //暫不明確(返回任何值都可以移動(dòng)挽荡,網(wǎng)上說的都是錯(cuò)的)
        //使用較少即供,一般不重寫
        public int getViewVerticalDragRange(@NonNull View child) {
            return 0;
        }
                //嘗試捕獲被拖拽的view,如果返回true代表可以被拖拽逗嫡,返回false代表不可以被拖拽
        //var1:被拖拽的view
        //使用時(shí)判斷需要被拖拽的view是否等等于var1。
        //一般判斷很多view其中哪些是否可以移動(dòng)時(shí)使用
        public abstract boolean tryCaptureView(@NonNull View var1, int var2);
                //返回view在水平方向的位置驱证,
        //left:當(dāng)前被拖拽的的view要移動(dòng)到的的left值
        //dx:移動(dòng)的偏移量
        //返回0則無法移動(dòng),通常直接返回left
        //一般必須重寫此方法返回left
        public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
            return 0;
        }
      
        //返回view在豎直方向的位置抹锄,
        //top:當(dāng)前被拖拽的的view要移動(dòng)到的的left值
        //dy:移動(dòng)的偏移量
        //返回0則無法移動(dòng)逆瑞,通常直接返回top
        //一般必須重寫此方法返回top
        public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
            return 0;
        }
    }

3. ViewDragHelper的使用

  • 先看一下常用到的方法
//以松手前的滑動(dòng)速度為初速動(dòng)荠藤,讓捕獲到的View自動(dòng)滾動(dòng)到指定位置。只能在Callback的onViewReleased()中調(diào)用获高。
settleCapturedViewAt(int finalLeft, int finalTop)
//以松手前的滑動(dòng)速度為初速動(dòng)哈肖,讓捕獲到的View在指定范圍內(nèi)fling。只能在Callback的onViewReleased()中調(diào)用谋减。
flingCapturedView(int minLeft, int minTop, int maxLeft, int maxTop)
//指定某個(gè)View自動(dòng)滾動(dòng)到指定的位置牡彻,初速度為0,可在任何地方調(diào)用出爹。
smoothSlideViewTo(View child, int finalLeft, int finalTop)
  • 再看使用:
    初始化并重寫需要用到的方法:
 viewDragHelper=  ViewDragHelper.create(this, new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(@NonNull View view, int i) {

                return true;
            }

            @Override
            public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
               return left;
           }

            @Override
            public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
                return top;
            }

           @Override
           public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
               super.onViewReleased(releasedChild, xvel, yvel);
                            super.onViewReleased(releasedChild, xvel, yvel);
                    //讓捕獲到的View自動(dòng)滾動(dòng)到100庄吼,300位置,只能在這里使用這個(gè)方法
               viewDragHelper.settleCapturedViewAt(100,300);
                 //讓捕獲到的View在100严就,100总寻,500,500這個(gè)范圍內(nèi)fling  梢为,只能在這里使用這個(gè)方法
               viewDragHelper.flingCapturedView(100,100,500,500);
               //指定某個(gè)View自動(dòng)滾動(dòng)到500渐行,500,初速度為0铸董,可在任何地方調(diào)用祟印。 
               viewDragHelper.smoothSlideViewTo(releasedChild,500,500);
               //以上方法必須手動(dòng)去刷新頁面
                             invalidate();
           }

       });


以上四個(gè)為常用的方法,然后獲取事件權(quán)限:

    @Override
    public boolean onInterceptHoverEvent(MotionEvent event) {
        return viewDragHelper.shouldInterceptTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        viewDragHelper.processTouchEvent(event);
        return true;

    }

之前說了粟害,ViewDragHelper內(nèi)部是overScroller完成計(jì)算的,那么和overScroller一樣需要重寫computeScroll()一直刷新頁面:

    @Override
    public void computeScroll() {
        super.computeScroll();
        //使用continueSettling(true)判斷拖拽是否完成
        if (viewDragHelper.continueSettling(true)){
            invalidate();
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蕴忆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子悲幅,更是在濱河造成了極大的恐慌套鹅,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件汰具,死亡現(xiàn)場離奇詭異卓鹿,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)留荔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門吟孙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人存谎,你說我怎么就攤上這事拔疚。” “怎么了既荚?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長栋艳。 經(jīng)常有香客問我恰聘,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任晴叨,我火速辦了婚禮凿宾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘兼蕊。我一直安慰自己初厚,他們只是感情好产禾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布牵啦。 她就那樣靜靜地躺著,像睡著了一般楞件。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上土浸,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天彭羹,我揣著相機(jī)與錄音,去河邊找鬼皆怕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛憋活,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播悦即,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼辜梳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了作瞄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤宗挥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后契耿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡透敌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年酗电,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片顾瞻。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡德绿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出移稳,到底是詐尸還是另有隱情,我是刑警寧澤古毛,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布都许,位于F島的核電站,受9級(jí)特大地震影響胶征,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜睛低,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望骂铁。 院中可真熱鬧,春花似錦拉庵、人聲如沸套蒂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至信夫,卻和暖如春卡啰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背匈辱。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留押搪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓大州,卻偏偏與公主長得像,于是被迫代替她去往敵國和親厦画。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 簡書個(gè)人檔案館23:靈感 作者:安居士/海濱 細(xì)心的讀者可能會(huì)發(fā)現(xiàn)根暑,我更文的時(shí)間主要集中在凌晨排嫌,或者第2天早晨6點(diǎn)...
    海濱公園閱讀 175評論 2 4
  • 上周六去香港買奶粉鹃栽,在深水埗買好了奶粉、洗頭精民鼓、染發(fā)劑......時(shí)間還很充裕,就信步逛逛街丰嘉。 深...
    葉滿秋塘閱讀 2,349評論 14 24
  • 從一八年高二上學(xué)期開學(xué)到一九年二十六日,我花了近半年時(shí)間看完了一本四百頁一百回的書――《西游記》饮亏。正常來說阅爽,看完應(yīng)...
    若若星游閱讀 208評論 0 0