天天看點

Android ViewDragHelper:控制子View垂直方向拖曳不能越界(3)



Android ViewDragHelper:控制子View垂直方向拖曳不能越界(3)

附錄文章1簡單介紹了Android ViewDragHelper的使用,附錄文章2介紹了如何控制ViewDragHelper在水準方向上拖曳不會被拖曳出邊界,以及那些子view可以被拖曳,那些子view不能被拖曳。

但是還有一些遺漏問題尚未解決:垂直方向的拖曳。本文再附錄文章2的基礎加以改進,控制子view在垂直方向上的拖曳不越界。技術路線仍然是計算并通過調節邊界極限坐标量實作。原理和附錄文章2中控制水準方向子view拖曳不越界原理相同。

在附錄文章2的MyLayout基礎上改進代碼,隻需在clampViewPositionVertical()裡面增加限制條件即可,其他代碼不變:

package zhangphil.demo;

import android.content.Context;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;


/**
 * Created by Phil on 2016/4/15.
 */
public class MyLayout extends LinearLayout {

    private ViewDragHelper mViewDragHelper;

    public MyLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        init();
    }

    private void init() {
        mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelperCallback());
    }

    private class ViewDragHelperCallback extends ViewDragHelper.Callback {

        @Override
        public boolean tryCaptureView(View view, int pointerId) {
            //假設我不希望紅色的子view可以被拖曳,那就加一層判斷,隻要是特定的view,直接傳回false,false告訴Android系統,這個子view是不允許拖曳操作的。
            if (view.getId() == R.id.red)
                return false;

            return true;
        }

        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {

            //控制左邊的拖曳距離,不能越界。
            //當拖曳的距離超過左邊的padding值,也意味着child view越界,複位
            //預設的padding值=0
            int paddingleft = getPaddingLeft();
            if (left < paddingleft) {
                return paddingleft;
            }

            //這裡是控制右邊的拖曳邊緣極限位置。
            //假設pos的值剛好是子view child右邊邊緣與父view的右邊重合的情況
            //pos值即為一個極限的最右邊位置,超過也即意味着拖曳越界:越出右邊的界限,複位。
            //可以再加一個paddingRight值,預設的paddingRight=0,是以即便不加也在多數情況正常可以工作
            int pos = getWidth() - child.getWidth() - getPaddingRight();
            if (left > pos) {
                return pos;
            }

            //其他情況屬于在範圍内的拖曳,直接傳回系統計算預設的left即可
            return left;
        }

        @Override
        public int clampViewPositionVertical(View child, int top, int dy) {
            //控制子view拖曳不能超過最頂部
            int paddingTop = getPaddingTop();
            if (top < paddingTop) {
                return paddingTop;
            }

            //控制子view不能越出底部的邊界。
            int pos = getHeight() - child.getHeight() - getPaddingBottom();
            if (top > pos) {
                return pos;
            }

            //其他情況正常,直接傳回Android系統計算的top即可。
            return top;
        }

        @Override
        public void onViewDragStateChanged(int state) {
            /**
             switch (state) {
             case ViewDragHelper.STATE_DRAGGING:
             // 正在拖動
             break;

             case ViewDragHelper.STATE_IDLE:
             // 沒有被拖拽或者正在進行fling/snap
             break;

             case ViewDragHelper.STATE_SETTLING:
             // fling完畢後被放置到一個位置
             break;
             }
             */
            super.onViewDragStateChanged(state);
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return mViewDragHelper.shouldInterceptTouchEvent(event);
    }

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

代碼運作結果:

附錄文章:

1,《Android ViewDragHelper(1)》連結位址:

http://blog.csdn.net/zhangphil/article/details/51177588

2,《Android ViewDragHelper:控制子View能否拖曳及水準方向的拖曳邊界(2)》連結位址:

http://blog.csdn.net/zhangphil/article/details/51179680

繼續閱讀