成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Android高手進階之ViewDragHelper使用詳解以及拖動上下滑卡片實現

開發 前端
今天我們就來講解下ViewDragHelper;ViewDragHelper是針對 ViewGroup 中的拖拽和重新定位 views 操作時提供了一系列非常有用的方法和狀態追蹤。

[[426553]]

前言

正好項目中有個頁面底部拖動上下滑的UI;

今天我們就來講解下ViewDragHelper;

這幾天項目比較忙,文章更新會慢,各位老鐵可以看歷史記錄;

一、viewDragHleper詳解

ViewDragHelper是針對 ViewGroup 中的拖拽和重新定位 views 操作時提供了一系列非常有用的方法和狀態追蹤;

1、ViewDragHelper初始化

  1. public class ViewDragTest extends LinearLayout  { 
  2.     ViewDragHelper mViewDragHelper; 
  3.     @Override 
  4.     protected void onAttachedToWindow() { 
  5.         super.onAttachedToWindow(); 
  6.         //中間參數表示靈敏度,比如滑動了多少像素才視為觸發了滑動.值越大越靈敏. 
  7.         mViewDragHelper = ViewDragHelper.create(this, 1f, new DragCallback()); 
  8.     } 
  9.     @Override 
  10.     public boolean onInterceptTouchEvent(MotionEvent ev) { 
  11.         //固定寫法 
  12.         int action = MotionEventCompat.getActionMasked(ev); 
  13.         if (action == MotionEvent.ACTION_CANCEL  
  14.         || action == MotionEvent.ACTION_UP) { 
  15.             mViewDragHelper.cancel(); 
  16.             return false
  17.         } 
  18.         return mViewDragHelper.shouldInterceptTouchEvent(ev); 
  19.     } 
  20.     @Override 
  21.     public boolean onTouchEvent(MotionEvent event) { 
  22.         //固定寫法 
  23.         mViewDragHelper.processTouchEvent(event); 
  24.         return true
  25.     } 
  26.     @Override 
  27.     public void computeScroll() { 
  28.         //固定寫法 
  29.         //此方法用于自動滾動,比如自動回滾到默認位置. 
  30.         if (mViewDragHelper.continueSettling(true)) { 
  31.             ViewCompat.postInvalidateOnAnimation(this); 
  32.         } 
  33.     } 

2、ViewDragHelper.Callback

  1. //這個類的回調方法,才是ViewDragHelper的重點 
  2. private class ViewDragCallback extends ViewDragHelper.Callback{ 
  3.    @Override 
  4.    public boolean tryCaptureView(View child, int pointerId) { 
  5.        //child 表示想要滑動的view 
  6.        //pointerId 表示觸摸點的id, 比如多點按壓的那個id 
  7.        //返回值表示,是否可以capture,也就是是否可以滑動.可以根據不同的child決定是否可以滑動 
  8.        return true
  9.    } 
  10.    @Override 
  11.    public int clampViewPositionHorizontal(View child, int leftint dx) { 
  12.        //child 表示當前正在移動的view 
  13.        //left 表示當前的view正要移動到左邊距為left的地方 
  14.        //dx 表示和上一次滑動的距離間隔 
  15.        //返回值就是child要移動的目標位置.可以通過控制返回值,從而控制child只能在ViewGroup的范圍中移動. 
  16.        return left
  17.    } 
  18.    @Override 
  19.    public int clampViewPositionVertical(View child, int topint dy) { 
  20.        //child 表示當前正在移動的view 
  21.        //top 表示當前的view正要移動到上邊距為top的地方 
  22.        //dx 表示和上一次滑動的距離間隔 
  23.        return top
  24.    } 

重寫以上3個方法,可以正常工作了.子View就可以被任意拖動了;

3、控制child的移動范圍在父view中

  1. //控制child只能在ViewGroup的橫向中移動 
  2. @Override   
  3. public int clampViewPositionHorizontal(View child, int leftint dx) { 
  4.   final int leftBound = getPaddingLeft();   
  5.   final int rightBound = getWidth() - mDragView.getWidth();   
  6.   final int newLeft = Math.min(Math.max(left, leftBound), rightBound);   
  7.   return newLeft;   
  8. }  
  9. //控制child只能在ViewGroup的縱向中移動 
  10. @Override   
  11. public int clampViewPositionVertical(View child, int topint dy) {   
  12.   final int topBound = getPaddingTop();   
  13.   final int bottomBound = getHeight() - mDragView.getHeight();   
  14.   final int newTop = Math.min(Math.max(top, topBound), bottomBound);   
  15.   return newTop;   
  16. }  

4、開啟邊界滑動

  1. //開啟4個邊 
  2. mViewDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_ALL); 
  3. //各個邊 
  4. public static final int EDGE_LEFT = 1 << 0; 
  5. public static final int EDGE_RIGHT = 1 << 1; 
  6. public static final int EDGE_TOP = 1 << 2; 
  7. public static final int EDGE_BOTTOM = 1 << 3; 
  8. //當開啟邊界滑動之后, 此方法就會回調 
  9. @Override 
  10. public void onEdgeTouched(int edgeFlags, int pointerId) { 
  11.     //通常開啟邊界之后, 都需要手動capture view.之后就可以滑動view了. 
  12.     mViewDragHelper.captureChildView(getChildAt(1), pointerId); 
  13. @Override 
  14. public boolean tryCaptureView(View child, int pointerId) { 
  15.     //開啟邊界之后, 這個方法的返回值可能需要進一步處理.要不然開邊界就沒啥意思了. 
  16.     return false

5、釋放后的回彈效果

有些時候, 當釋放的時候, 需要將View回到原來的位置;

  1. //釋放的時候, 會回調下面的方法 
  2. @Override 
  3. public void onViewReleased(View releasedChild, float xvel, float yvel) { 
  4.     //調用這個方法,就可以設置releasedChild回彈得位置. 
  5.     mViewDragHelper.settleCapturedViewAt(0, 100);//參數就是x,y的坐標 
  6.     postInvalidate();//注意一定要調用這個方法,否則沒效果. 
  7. //以下2個方法最終調用的都是forceSettleCapturedViewAt(). 
  8. mViewDragHelper.settleCapturedViewAt(0, 100); 
  9. mViewDragHelper.smoothSlideViewTo(getChildAt(1), 0, 100); 
  10. //所以...發揮你的想象力,看看有什么妙用!!! 
  11. //如果你還沒有忘記的話...前文應該有說過,涉及到scroll,需要重寫view的此方法. 
  12. //此方法一定要重寫,否則沒效果 
  13. @Override 
  14. public void computeScroll() { 
  15.   //固定寫法 
  16.   if (mViewDragHelper.continueSettling(true)) { 
  17.       postInvalidate();//注意此處. 
  18.   } 
  19. 通過上面2個方法的設置, 當手指釋放的時候, View就會自動滑動到指定的位置...(不是一下子就到指定的位置哦,有一個滑動的過程.) 
  20. 注意:如果需要滑動的View,會消耗touch事件,比如:Button,那么需要重寫以下方法. 
  21. @Override 
  22. public int getViewHorizontalDragRange(View child) { 
  23.     return child.getMeasuredWidth();//只要返回大于0的值就行 
  24. @Override 
  25. public int getViewVerticalDragRange(View child) { 
  26.     return child.getMeasuredHeight();//只要返回大于0的值就行 

6、簡單api介紹

ViewDragHelper的API

  1. ViewDragHelper create(ViewGroup forParent, Callback cb); 
  • 一個靜態的創建方法,
  • 參數1:出入的是相應的ViewGroup
  • 參數2:是一個回掉
  1. shouldInterceptTouchEvent(MotionEvent ev)  
  • 處理事件分發的(主要是將ViewGroup的事件分發,委托給ViewDragHelper進行處理)
  • 參數1:MotionEvent ev 主要是ViewGroup的事件
  • processTouchEvent(MotionEvent event) 處理相應TouchEvent的方法,這里要注意一個問題,處理相應的TouchEvent的時候要將結果返回為true,消費本次事件!否則將無法使用ViewDragHelper處理相應的拖拽事件!

ViewDragHelper.Callback的API

  1. tryCaptureView(View child, int pointerId)  
  • 這是一個抽象類,必須去實現,也只有在這個方法返回true的時候下面的方法才會生效;
  • 參數1:捕獲的View(也就是你拖動的這個View)
  1. onViewDragStateChanged(int state)  
  • 當狀態改變的時候回調,返回相應的狀態(這里有三種狀態)
  • STATE_IDLE 閑置狀態
  • STATE_DRAGGING 正在拖動
  • STATE_SETTLING 放置到某個位置
  1. onViewPositionChanged(View changedView, int leftint topint dx, int dy)  
  • 當你拖動的View位置發生改變的時候回調
  • 參數1:你當前拖動的這個View
  • 參數2:距離左邊的距離
  • 參數3:距離右邊的距離
  • 參數4:x軸的變化量
  • 參數5:y軸的變化量
  1. onViewCaptured(View capturedChild, int activePointerId) 
  • 捕獲View的時候調用的方法
  • 參數1:捕獲的View(也就是你拖動的這個View)
  1. onViewReleased(View releasedChild, float xvel, float yvel)  
  • 當View停止拖拽的時候調用的方法,一般在這個方法中重置一些參數,比如回彈什么的
  • 參數1:你拖拽的這個View
  • 參數2:x軸的速率
  • 參數3:y軸的速率
  1. clampViewPositionVertical(View child, int topint dy)  
  • 豎直拖拽的時候回調的方法
  • 參數1:拖拽的View
  • 參數2:距離頂部的距離
  • 參數3:變化量
  1. clampViewPositionHorizontal(View child, int leftint dx)  
  • 水平拖拽的時候回調的方法
  • 參數1:拖拽的View
  • 參數2:距離左邊的距離
  • 參數3:變化量

二、簡單的實現demo

下面是簡單實現的demo,可以直接復制使用的

1、BottomView的ViewDragHelper實現

  1. public class BottomView extends LinearLayout { 
  2.     private ViewDragHelper mDragHelper; 
  3.     private View view
  4.     private int mDragBorder, verticalRange, mDragState, peekHeight, mDragHeight; 
  5.     private final double AUTO_OPEN_SPEED_LIMIT = 800.0; 
  6.     private boolean inflate = false, isExpanded = false, isDragHeightSet = false
  7.     private MotionEvent globalEvent; 
  8.     View try_view; 
  9.     public BottomView(Context context) { 
  10.         super(context); 
  11.     } 
  12.     public BottomView(Context context, @Nullable AttributeSet attrs) { 
  13.         super(context, attrs); 
  14.         initView(context, attrs); 
  15.     } 
  16.     public BottomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 
  17.         super(context, attrs, defStyleAttr); 
  18.         initView(context, attrs); 
  19.     } 
  20.     void initView(Context context, AttributeSet attrs) { 
  21.         peekHeight = 300; 
  22.     } 
  23.     @Override 
  24.     protected void onAttachedToWindow() { 
  25.         super.onAttachedToWindow(); 
  26.     } 
  27.     @Override 
  28.     protected void onFinishInflate() { 
  29.         super.onFinishInflate(); 
  30.         mDragHelper = ViewDragHelper.create(this, 1.0f, new DragHelperCallback()); 
  31.         view = getChildAt(0); 
  32.         try_view = findViewById(R.id.ll_try_view); 
  33.     } 
  34.     @Override 
  35.     protected void onLayout(boolean b, int leftint topint rightint bottom) { 
  36.         verticalRange = getMeasuredHeight() - peekHeight; 
  37.         if (!inflate) { 
  38.             mDragBorder = verticalRange; 
  39.             inflate = true
  40.         } 
  41.         view.layout(left, mDragBorder, right, bottom + mDragBorder); 
  42.     } 
  43.     @Override 
  44.     public boolean onInterceptTouchEvent(MotionEvent ev) { 
  45.         int action = MotionEventCompat.getActionMasked(ev); 
  46.         if ((action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) && !isDraggingAllowed(ev)) { 
  47.             mDragHelper.cancel(); 
  48.             return false
  49.         } 
  50.         return mDragHelper.shouldInterceptTouchEvent(ev); 
  51.     } 
  52.     @Override 
  53.     public boolean onTouchEvent(MotionEvent event) { 
  54.         if (isDraggingAllowed(event) || isMoving()) { 
  55.             mDragHelper.processTouchEvent(event); 
  56.             return true
  57.         } 
  58.         return super.onTouchEvent(event); 
  59.     } 
  60.     @Override 
  61.     public boolean dispatchTouchEvent(MotionEvent ev) { 
  62.         globalEvent = ev; 
  63.         return super.dispatchTouchEvent(ev); 
  64.     } 
  65.     boolean isDraggingAllowed(MotionEvent event) { 
  66.         int[] viewLocations = new int[2]; 
  67.         view.getLocationOnScreen(viewLocations); 
  68.         int upperLimit = viewLocations[1] + (isDragHeightSet ? mDragHeight : peekHeight); 
  69.         int lowerLimit = viewLocations[1]; 
  70.         int y = (int) event.getRawY(); 
  71.         return (y > lowerLimit && y < upperLimit); 
  72.     } 
  73.     boolean isMoving() { 
  74.         return (mDragState == ViewDragHelper.STATE_DRAGGING || 
  75.                 mDragState == ViewDragHelper.STATE_SETTLING); 
  76.     } 
  77.     class DragHelperCallback extends ViewDragHelper.Callback { 
  78.         @Override 
  79.         public boolean tryCaptureView(View child, int pointerId) { 
  80.             return true
  81.         } 
  82.         @Override 
  83.         public int clampViewPositionVertical(View child, int topint dy) { 
  84.             return top
  85.         } 
  86.         @Override 
  87.         public void onViewDragStateChanged(int state) { 
  88.             super.onViewDragStateChanged(state); 
  89.             mDragState = state; 
  90.         } 
  91.         @Override 
  92.         public int getViewVerticalDragRange(View child) { 
  93.             return verticalRange; 
  94.         } 
  95.         @Override 
  96.         public void onViewReleased(View releasedChild, float xvel, float yvel) { 
  97.             super.onViewReleased(releasedChild, xvel, yvel); 
  98.             boolean settleToOpen = false
  99.             if (yvel > AUTO_OPEN_SPEED_LIMIT && xvel < yvel) { 
  100.                 settleToOpen = true
  101.             } else if (yvel < -AUTO_OPEN_SPEED_LIMIT && xvel > yvel) { 
  102.                 settleToOpen = false
  103.             } else if (mDragBorder > (2 * verticalRange / 3)) { 
  104.                 settleToOpen = true
  105.             } else if (mDragBorder < (verticalRange / 3)) { 
  106.                 settleToOpen = false
  107.             } 
  108.             final int settleDestY = settleToOpen ? verticalRange : 0; 
  109.             isExpanded = settleToOpen ? false : true
  110.             if (mDragHelper.settleCapturedViewAt(releasedChild.getLeft(), settleDestY)) { 
  111.                 ViewCompat.postInvalidateOnAnimation(BottomView.this); 
  112.             } 
  113.         } 
  114.         @Override 
  115.         public void onViewPositionChanged(View changedView, int leftint topint dx, int dy) { 
  116.             super.onViewPositionChanged(changedView, lefttop, dx, dy); 
  117.             mDragBorder = top < 0 ? 0 : top > verticalRange ? verticalRange : top
  118.             float offset = 1 - ((float) mDragBorder / verticalRange); 
  119.            // if (listener != null) listener.onDrag(offset); 
  120.             requestLayout(); 
  121.         } 
  122.     } 
  123.     @Override 
  124.     public void computeScroll() { 
  125.         super.computeScroll(); 
  126.         if (mDragHelper.continueSettling(true)) { 
  127.             ViewCompat.postInvalidateOnAnimation(this); 
  128.         } 
  129.     } 
  130.     public boolean expandOnTouchView() { 
  131.         if (isDraggingAllowed(globalEvent) && mDragHelper.smoothSlideViewTo(view, 0, 0)) { 
  132.             isExpanded = true
  133.             ViewCompat.postInvalidateOnAnimation(BottomView.this); 
  134.             return true
  135.         } 
  136.         return false
  137.     } 
  138.     public boolean expandView() { 
  139.         if (mDragHelper.smoothSlideViewTo(view, 0, 0)) { 
  140.             isExpanded = true
  141.             ViewCompat.postInvalidateOnAnimation(BottomView.this); 
  142.             return true
  143.         } 
  144.         return false
  145.     } 
  146.     public boolean collapseOnTouchView() { 
  147.         if (isDraggingAllowed(globalEvent) && mDragHelper.smoothSlideViewTo(view, 0, verticalRange)) { 
  148.             isExpanded = false
  149.             ViewCompat.postInvalidateOnAnimation(BottomView.this); 
  150.             return true
  151.         } 
  152.         return false
  153.     } 
  154.     public boolean collapseView() { 
  155.         if (mDragHelper.smoothSlideViewTo(view, 0, verticalRange)) { 
  156.             isExpanded = false
  157.             ViewCompat.postInvalidateOnAnimation(BottomView.this); 
  158.             return true
  159.         } 
  160.         return false
  161.     } 
  162.     public boolean isViewExpanded() { 
  163.         return isExpanded; 
  164.     } 
  165.     public void setPeekHeight(int peekHeight) { 
  166.         this.peekHeight = peekHeight; 
  167.         requestLayout(); 
  168.     } 
  169.     public void dragHeight(int mDragHeight) { 
  170.         isDragHeightSet = true
  171.         this.mDragHeight = mDragHeight; 
  172.     } 

2、布局文件

總結

面對不懂的知識點,不要害怕,勇敢面對;一起加油

本文轉載自微信公眾號「Android開發編程」

 

責任編輯:姜華 來源: Android開發編程
相關推薦

2021-09-09 06:55:43

AndroidViewDragHel原理

2021-08-23 06:27:46

AndroidctivitysetContentV

2021-07-14 14:27:01

AndroidAOPhugo

2021-08-25 07:43:17

AndroidSurfaceViewTextureView

2021-09-14 07:06:12

Android磁盤緩存

2021-09-12 07:30:10

配置

2021-09-07 06:40:25

AndroidLiveData原理

2021-08-09 20:29:27

Android沉浸式狀態欄

2015-07-28 17:11:00

編程技術提升

2021-08-10 20:41:33

AndroidApp流程

2021-09-01 06:48:16

AndroidGlide緩存

2021-10-03 15:08:32

Android

2009-07-16 13:51:43

2021-08-17 13:41:11

AndroidView事件

2021-09-02 07:00:01

Glide流程Android

2014-07-15 17:17:31

AdapterAndroid

2022-04-24 15:26:38

服務卡鴻蒙

2021-08-11 17:15:17

AndroidActivity場景

2021-08-26 07:38:41

AndroidMediaPlayerTextureView

2021-09-03 07:27:38

AndroidGlide管理
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产女人叫床高潮大片免费 | hdfreexxxx中国妞 | 伊人狠狠操 | 91欧美精品成人综合在线观看 | 国产 欧美 日韩 一区 | 精品一区二区三区在线观看 | av久久 | 97久久超碰 | 国产精品精品久久久 | 久久久精 | 爱爱爱av| 国产成人精品久久二区二区 | 视频一区二区三区中文字幕 | 国产清纯白嫩初高生在线播放视频 | 精品视频一区二区 | 国产精品久久国产精品 | 亚洲精品一区二三区不卡 | 国产成人一区二区三区电影 | 日韩乱码在线 | 99精品免费 | 欧美福利专区 | 久久久久久久久久久久久久av | 99久久久久久99国产精品免 | 国产成人在线视频免费观看 | 中文字幕在线免费观看 | 国产成人精品一区二区三区网站观看 | 先锋av资源在线 | 一区在线视频 | 久久久久久高潮国产精品视 | 久久久www成人免费无遮挡大片 | 中文字幕 国产精品 | 毛片网在线观看 | 男女羞羞视频在线观看 | 中文字幕乱码一区二区三区 | 精品视频在线一区 | www亚洲免费国内精品 | 国产日韩久久 | 中文在线一区二区 | 免费观看一级毛片 | 国产小视频自拍 | 久久夜色精品国产 |