通過我們來處理自定義ViewGroup中子View滑動時,我們都是去通過事件攔截以及在onTouchEvent方法中進行手勢判斷,加速度檢測等。
在官方的V4提供了ViewDragHelper來幫助我們方便的編寫自定義ViewGroup時處理子View的滑動等相關的操作處理
代碼演示:
public class CustomViewGroup extends ViewGroup {
View childView_1; //子View1
View childView_2; //子View2
ViewDragHelper viewDragHelper;
public CustomViewGroup(Context context) {
super(context);
// 第一個參數爲this,表示該類生成的對象,是ViewDragHelper的拖動處理對象,必須爲ViewGroup。
//第二個參數1.0f是敏感度參數參數越大越敏感,默認就是1.0f。
//第三個參數回調接口,是ViewDragHelper與View交互的橋樑
viewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
/**
*通過DragHelperCallback的tryCaptureView方法的返回值可以決定一個parentview中哪個子view可以拖動,
*
* @param child
* @param pointerId
* @return
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
//return child==childView_1; 如果如此 設置 只有 childView_1可以被ViewDragHelper控制
return true; //所有View都可以
//有人問 想 控制兩個怎麼辦
//return child == view1 || child == view2 >>>>> 484傻 ,其實是我問的
}
/**
*該方法用來處理水平方向的滑動事件,返回目的值即可,但是爲了處理例如邊界情況,需要考慮到對象本身的邊界值
* @param child 需要被處理的對象 可以用此來判斷(eg 只允許View1垂直滑動 ,判斷一下,如果是view1我就不做任何操作不就行了麼)
* @param left 目的值(應該是以左邊的點爲依據)
* @param dx
* @return
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
int left_bound = getPaddingLeft(); //左邊的邊界值
int right_bound = getWidth() - getPaddingRight() - child.getWidth();//右邊的邊界值
//這真是個有趣的表達式 第一步如果是左邊部分的話,肯定是取值比 左邊界要大,
// 右邊部分的話(肯定比左邊界大了,內部的值Max取到的肯定是 left),取到的值要比右邊界小
//主要是爲了 視圖越界 呈現在手機窗口的外面了
return Math.min(Math.max(left, left_bound), right_bound);
}
/*
* 這裏沒有什麼不同 只是垂直方向的罷了
* */
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
int top_bound = getPaddingTop();//上邊界
int bottom_bound = getHeight() - getPaddingBottom() - child.getHeight();//下邊界
return Math.min(Math.max(top, top_bound), bottom_bound);
}
/**
* 當設置了邊緣滑動事件的時候,一旦事件發生,該方法就會被回調,要是想要相關View跟着運動需要在代碼中執行
* @param edgeFlags 邊緣的滑動標誌
* @param pointerId
*/
@Override
public void onEdgeDragStarted(int edgeFlags, int pointerId) {
//如此 第一個View就會跟着邊緣事件進行 觸發操作了
viewDragHelper.captureChildView(childView_1, pointerId);
}
});
//如果你想要處理左右邊緣的滑動事件 可以通過以下設置 >>例如設置左邊緣,如果想要監聽到相關事件還需要重寫回調中的一個方法
//onEdgeDragStarted()
viewDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//該方法內部已經對相應的事件進行了過濾,至此直接將事件交給ViewDragHelper返回即可
return viewDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//將事件拿到
viewDragHelper.processTouchEvent(event);
//表示消費該事件
return true;
}
/**
* 當View中所有的子控件 均被映射成xml後觸發
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
//小心空指針呀,要是你佈局文件裏沒有兩個子View,不就GG了麼 注意哈
childView_1 = getChildAt(0);
childView_2 = getChildAt(1);
}
}
到此,我們的ViewDragHelper已經體驗了一番,下一章,我們介紹剩下的幾個特性,打造我們的側滑菜單.