关于从边测划出控件

原创 2016年05月31日 17:22:02
最近使用滴滴打车,因为要打印发票才发现原来滴滴打车还有个侧边栏,不过不能划开,需要点击打开。估计是因为和里面的地图冲突,所以才这么设计的。于是自己实现了个小的控件去进行了改善。主要思想就是监听滑动事件,如果是在边上则当前的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();
        }
    }

}

android自定义控件实现左右划出菜单并添加点击事件

public class SwipeItemView extends View { public SwipeItemView(Context context) { super(...

连接数据库的鼠标划出菜单

  • 2008年08月26日 12:22
  • 556B
  • 下载

使用WPF五子棋_自动划出方格

  • 2011年09月21日 20:56
  • 234KB
  • 下载

android的Popupwindow根据手势来贴边划出

刚刚开始学习android,没事的时候想实现一下Popupwindow依靠手势来贴边弹出,在网上东抄西抄终于完成了,代码贴上。 /** *获取屏幕大小的类 **/ package modle.d...

底部划出菜单使用POPWindow

怎么实现底部动画划出一个菜单,使用POPWindows是个不错的xuanz

android 实现view从屏幕中间划出

一、概述 前几天接到一个需求,就是一个LinearLayout从屏幕的中间划出,之前我是一点头绪没有的的,可是后来我想到了属性动画这个好东西,然后我先和大家说一下我的思路: 1、首先我们要实现的就是滑...

修改DrawerLayout只能从屏幕边缘划出的方法

方法来自Stack OverFlow,利用反射,修改DrawLayout的侧滑菜单的感应范围,代码如下: public class MainActivity extends Activity { pr...
  • czfyzy
  • czfyzy
  • 2015年01月13日 19:34
  • 1173

解决iscroll.js上拉下拉刷新手指划出屏幕页面无法回弹问题

使用过iscroll.js的上拉下拉刷新效果的朋友应该都碰到过这个问题:在iOS的浏览器中,上拉或下拉刷新时,当手指划出屏幕后,页面无法弹回。很多人因为解决不了这个问题,干脆就那样不解决了,还有的直接...
  • jjx0224
  • jjx0224
  • 2017年03月29日 11:44
  • 279
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于从边测划出控件
举报原因:
原因补充:

(最多只允许输入30个字)