聲明:非原創(chuàng)
ViewDragHelper是什么
viewDragHelper是寫自定義ViewGroups的工具類季研,對于用戶處理views在它的父容器里面的拖動以及相對應(yīng)的響應(yīng)弱左,它提供了豐富有用的操作和狀態(tài)跟蹤的API
ViewDragHelper創(chuàng)建
image
- Viewgroup——與 ViewDragHelper 相關(guān)聯(lián)的 ViewGroup蚕冬。
- ViewDragHelper.Callback cb ——ViewDragHelper.Callback 是個回調(diào)
ViewDragHelper.Callback
ViewDragHelper 提供了一系列回調(diào)誊抛,一下是全部回調(diào)
// 控制橫軸的移動距離
int clampViewPositionHorizontal(View child, int left, int dx)
//控制縱軸的移動距離
int clampViewPositionVertical(View child, int top, int dy)
// 獲取子視圖的Z值
int getOrderedChildIndex(int index)
//獲取視圖在橫軸移動的距離
int getViewHorizontalDragRange(View child)
//獲取視圖在縱軸移動的距離
int getViewVerticalDragRange(View child)
//處理當(dāng)用戶觸碰邊界移動開始的回調(diào)
void onEdgeDragStarted(int edgeFlags, int pointerId)
//處理邊界被鎖定時的回調(diào)
boolean onEdgeLock(int edgeFlags)
//處理邊界被觸碰時的回調(diào)
void onEdgeTouched(int edgeFlags, int pointerId)
//當(dāng)視圖被捕獲時的回調(diào)
void onViewCaptured(View capturedChild, int activePointerId)
//當(dāng)視圖的拖動狀態(tài)改變的時候的回調(diào)
void onViewDragStateChanged(int state)
//當(dāng)捕獲的視圖位置發(fā)生改變的時候的回調(diào)
void onViewPositionChanged(View changedView, int left, int top, int dx, int dy)
//當(dāng)視圖的拖動被釋放的時候的回調(diào)
void onViewReleased(View releasedChild, float xvel, float yvel)
// 判斷此時的視圖是否為想要捕獲的視圖時會調(diào)用
abstract boolean tryCaptureView(View child, int pointerId)
作為初學(xué)者,我們要用最少的代碼把ViewDragHelper創(chuàng)建出來
ViewDragHelper 用哪幾個回調(diào)能構(gòu)成最簡單能運(yùn)行的實(shí)例呢锥债?
// 決定了是否需要捕獲這個 child,只有捕獲了才能進(jìn)行下面的拖拽行為
abstract boolean tryCaptureView(View child, int pointerId)
// 修整 child 水平方向上的坐標(biāo)践樱,left 指 child 要移動到的坐標(biāo),dx 相對上次的偏移量
int clampViewPositionHorizontal(View child, int left, int dx)
// 修整 child 垂直方向上的坐標(biāo)凸丸,top 指 child 要移動到的坐標(biāo)拷邢,dy 相對上次的偏移量
int clampViewPositionVertical(View child, int top, int dy)
// 手指釋放時的回調(diào)
void onViewReleased(View releasedChild, float xvel, float yvel)
ViewDragHelper使用
拖拽的相關(guān)方法
/** 是否應(yīng)該攔截 children 的觸摸事件,
*只有攔截了 ViewDragHelper 才能進(jìn)行后續(xù)的動作
*
*將它放在 ViewGroup 中的 onInterceptTouchEvent() 方法中就好了
**/
boolean shouldInterceptTouchEvent(MotionEvent ev)
/** 處理 ViewGroup 中傳遞過來的觸摸事件序列
*在 ViewGroup 中的 onTouchEvent() 方法中處理
*/
void processTouchEvent(MotionEvent ev)
拖拽后回彈
相關(guān)方法
//將 child 安置到坐標(biāo) (final Left,final Top) 的位置甲雅。
settleCapturedViewAt(int finalLeft, int finalTop)
// 在此方法中記錄拖拽前的坐標(biāo)
void onViewCaptured(View capturedChild, int activePointerId)
思路:
- 在 onViewCaptured() 方法中 或者 viewgroup的onLayout() 記錄拖拽前的坐標(biāo)解孙。
- 在 onViewReleased() 方法中調(diào)用 settleCapturedViewAt() 方法來重定位 child。
邊緣觸發(fā)
相關(guān)API
//處理當(dāng)用戶觸碰邊界移動開始的回調(diào)
void onEdgeDragStarted(int edgeFlags, int pointerId)
//處理邊界被鎖定時的回調(diào)
boolean onEdgeLock(int edgeFlags)
//處理邊界被觸碰時的回調(diào)
void onEdgeTouched(int edgeFlags, int pointerId)
思路
- tryCaptureView 返回true使得view可以被捕獲
- onEdgeDragStarted 中使用 captureChildView 捕獲特定的view
- mDragHelper.setEdgeTrackingEnabled() 設(shè)置邊緣出發(fā)
移動button
因?yàn)?Button 本身能夠響應(yīng)點(diǎn)擊事件抛人,那么 ViewDragHelper 移動button需要特殊處理
這兩個方法只要返回值大于 0 疲陕,那么它就可以滑動胯努。
@Override
public int getViewHorizontalDragRange(View child) {
? return 1;
}
@Override
public int getViewVerticalDragRange(View child) {
? return 1;
}
注意
- tryCaptureView() 方法返回 true 時才會導(dǎo)致下面的回調(diào)方法被調(diào)用
- 邊緣觸發(fā)的邊緣指的是 這個viewgroup的邊緣步悠,而非屏幕的邊緣