关于从边测划出控件

来源:互联网 发布:数据分析专业排名 编辑:程序博客网 时间:2024/04/30 15:25
最近使用滴滴打车,因为要打印发票才发现原来滴滴打车还有个侧边栏,不过不能划开,需要点击打开。估计是因为和里面的地图冲突,所以才这么设计的。于是自己实现了个小的控件去进行了改善。主要思想就是监听滑动事件,如果是在边上则当前的view处理,如果超过了边缘则传递给子view去处理。后面又发现了viewDragerhelper这个东东,于是更简单了~
public class MyView extends ViewGroup {    private ViewDragHelper mDragger;    //被滑动的view    private View mDragView;    //边缘是否被触摸    private boolean isEdgeTouched;    //监听滑动速度    private VelocityTracker vTracker = null;    //是否打开    private boolean isOpen;    //自定义属性,可以打开的距离    float cap;    public MyView(Context context, AttributeSet attrs) {        super(context, attrs);        TypedArray a = context.obtainStyledAttributes(attrs,                R.styleable.MyView);        int n = a.getIndexCount();        for (int i = 0; i < n; i++) {            int attr = a.getIndex(i);            switch (attr) {                case R.styleable.MyView_cap:                    //获得可以打开的距离,转化为px单位                    cap = a.getDimensionPixelSize(attr, 250);            }        }        a.recycle();        mDragger = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {            @Override            public boolean tryCaptureView(View child, int pointerId) {                //只有边缘被触摸,才返回滑动的view                if (isEdgeTouched)                    return mDragView == child;                else                    return false;            }            @Override            public int clampViewPositionHorizontal(View child, int left, int dx) {                final int leftBound = getPaddingLeft();                return Math.min(Math.max(left, leftBound), getWidth() - (int) cap);            }            @Override            public void onEdgeDragStarted(int edgeFlags, int pointerId) {                isEdgeTouched = true;                mDragger.captureChildView(mDragView, pointerId);            }            //手指释放的时候回调            @Override            public void onViewReleased(View releasedChild, float xvel, float yvel) {                if (releasedChild == mDragView) {                    //如果正向滑动,没有打开并且速度大于每秒5,直接打开view                    if (xvel > 5 && !isOpen) {                        //这里以自定义属性gap为打开的距离                        mDragger.settleCapturedViewAt(getWidth() - (int) cap, getTop());                        invalidate();                        isOpen = true;                        return;                    }                    //如果负向滑动,已经打开并且速度大于每秒5,直接关闭view                    if (xvel < -5 && isOpen) {                        mDragger.settleCapturedViewAt(0, getTop());                        isEdgeTouched = false;                        invalidate();                        isOpen = false;                        return;                    }                    //判断滑动的距离是否超过最大距离的一半,有则打开                    if (mDragView.getLeft() > (getWidth() - cap) / 2) {                        mDragger.settleCapturedViewAt(getWidth() - (int) cap, getTop());                        invalidate();                        isOpen = true;                        return;                    }                    //判断滑动的距离是否小于等于最大距离的一半,是则关闭                    if (mDragView.getLeft() <= (getWidth() - cap) / 2) {                        mDragger.settleCapturedViewAt(0, getTop());                        isEdgeTouched = false;                        invalidate();                        isOpen = false;                        return;                    }                }            }        });        mDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int count = this.getChildCount();        for (int i = 0; i < count; i++) {            View child = this.getChildAt(i);            child.measure(widthMeasureSpec, heightMeasureSpec);        }    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        for (int i = 0, size = getChildCount(); i < size; i++) {            if (i == 0) {                View view = getChildAt(i);                view.layout(left, top, right - (int) cap, bottom);            } else {                View view = getChildAt(i);                view.layout(left, top, right, bottom);                mDragView = view;            }        }    }    @Override    public boolean onInterceptTouchEvent(MotionEvent event) {        //如果view打开了,则当前view处理滑动事件,也就是说view打开后可以通过手势滑回去,把关注点放在打开的view        if (isOpen) {            return true;        } else            return mDragger.shouldInterceptTouchEvent(event);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        if (vTracker == null) {            vTracker = VelocityTracker.obtain();        } else {            vTracker.clear();        }        //监听滑动速度,以每秒多少个像素为单位        vTracker.addMovement(event);        vTracker.computeCurrentVelocity(1000);//10001000毫秒        mDragger.processTouchEvent(event);        return true;    }    @Override    public void computeScroll() {        if (mDragger.continueSettling(true)) {            invalidate();        }    }}

0 0