Android ViewDragHelper 实例

1,072 阅读3分钟

公布下昨天中奖结果,分别是:

【M。】他的评论是“妈呀,昨天郭神那里抽书,我排第六,没捞着!这次说什么我也要上前排啊!!我要这个东西!我还没女朋友!”,好的,满足你,送你大波美女鼠标垫,小撸怡情大撸伤身,祝你过年能带个女票回家。

【舒格】她的评论是“最后的福利让程序媛情何以堪……”,既然鼠标福利不合适,那就送公仔吧,感谢支持。

奖品需要等公仔寄给我,我再一并寄出去哈,后台我已经联系你们了,以后有什么福利,我还是会及时地反馈给大家,感谢大家一直以来的支持,谢谢了。

ViewDragHelper创建

//创建ViewDragHelper的实例,第一个参数是ViewGroup,传自己,
// 第二个参数就是滑动灵敏度的意思,可以随意设置,第三个是回调
ViewDragHelper mViewDragHelper = ViewDragHelper.create(this,1.0f, new DragHelperCallback());

ViewDragHelper主要重写它的Callback方法,即这里的DragHelperCallback:

class DragHelperCallback extends ViewDragHelper.Callback {    
    /**
     * 根据返回结果决定当前child是否可以拖拽
     *
     * @param child     当前被拖拽的view
     * @param pointerId 区分多点触摸的id
     * @return
     */
    @Override
    public boolean tryCaptureView(View child, int pointerId) {        
        return mContentLayout == child;
    }    
    /**
     * 返回拖拽的范围,不对拖拽进行真正的限制,仅仅决定了动画执行速度
     *
     * @param child
     * @return
     */
    @Override
    public int getViewHorizontalDragRange(View child) {        
        return mContentLayoutWidth;
    }    
    /**
     * @param child
     * @param left  代表你将要移动到的位置的坐标,返回值就是最终确定的移动的位置,
     *              判断如果这个坐标在layout之内,那我们就返回这个坐标值,
     *              不能让他超出这个范围, 除此之外就是如果你的layout设置了padding的话,
     *              让子view的活动范围在padding之内的
     * @param dx
     * @return
     */
    @Override
    public int clampViewPositionHorizontal(View child, int left, int dx) {       
        if (child == mContentLayout) {
                int newLeft = Math.min(
                    Math.max((-getPaddingLeft() - mBehindLayoutWidth), left), 0);
                 return newLeft;
        } else {
                int newLeft = Math.min(
                    Math.max(left, getPaddingLeft() + mContentLayoutWidth - mBehindLayoutWidth),
                    (getPaddingLeft() + mContentLayoutWidth + getPaddingRight()));
                 return newLeft;
        }
    }    
    /**
     * 位置改变时回调,常用于滑动是更改scale进行缩放等效果
     *
     * @param changedView
     * @param left
     * @param top
     * @param dx          横向滑动的加速度
     * @param dy
     */
    @Override
    public void onViewPositionChanged(
            View changedView, int left, int top, int dx, int dy) {        
            mViewDragRange = left;
            float percent = Math.abs((float) left / (float) mContentLayoutWidth) 
            if (null != mViewDragListener)
            mViewDragListener.onDrag(percent);        
            if (changedView == mContentLayout) {
            mBehindLayout.offsetLeftAndRight(dx);
        } else {
            mContentLayout.offsetLeftAndRight(dx);
        }
        invalidate();
    }    
    /**
     * 拖动结束后调用
     *
     * @param releasedChild
     * @param xvel          水平方向的速度  向右为正
     * @param yvel          竖直方向的速度  向下为正
     */
    @Override
    public void onViewReleased(View releasedChild, float xvel, float yvel) {        
        if (releasedChild == mContentLayout) {
                if (xvel <= 0)="" {="" 向左滑动="" if="" (-mviewdragrange="">= mBehindLayoutWidth / 2
                        && -mViewDragRange <= mbehindlayoutwidth)="" {="" open();="" }="" else="" close();="" 向右滑动="" if="" (-mviewdragrange="">= 0
                        && -mViewDragRange <= mbehindlayoutwidth)="" {="" close();="" }="" else="" open();="" <="" code="">

实例

实例代码

public class ViewDragLayout extends LinearLayout {    
    /**
     * 内容界面
     */
    private ViewGroup mContentLayout;
     /**
     * 遮盖界面
     */
    private ViewGroup mBehindLayout;    
    private ViewDragHelper mViewDragHelper;    
     /**
     * 手势事件类
     */
    private GestureDetectorCompat mGestureDetectorCompat;    
     /**
     * 滑动距离
     */
    private int mViewDragRange;    
     /**
     * 左滑最大距离
     */
    private int mBehindLayoutWidth;    
     /**
     * 宽度
     */
    private int mContentLayoutWidth;    
    private ViewDragListener mViewDragListener;    
    private boolean isOpen = false;   
    
     /**
     * 构造方法省略
     */
    
     /**
     * View 中所有的子控件均被映射成xml后触发
     */
    @Override
    protected void onFinishInflate() {
        mContentLayout = (ViewGroup) getChildAt(0);
        mBehindLayout = (ViewGroup) getChildAt(1);
        mBehindLayout.setClickable(true);
        mContentLayout.setClickable(true);        
        super.onFinishInflate();
    }    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mContentLayoutWidth = mContentLayout.getMeasuredWidth();
        mBehindLayoutWidth = mBehindLayout.getMeasuredWidth();

    }    
    /**
     * 设置监听
     */
    public void setOnViewDragListener(ViewDragListener viewDragListener) {        
    this.mViewDragListener = viewDragListener;
    }    
    
    public interface ViewDragListener {        
    void onOpen();        
    void onClose();        
    void onDrag(float percent);

    }    
    /**
     * 滑动时松手后以一定速率继续自动滑动下去并逐渐停止,
     * 类似于扔东西或者松手后自动滑动到指定位置
     */
    @Override
    public void computeScroll() {        
    if (mViewDragHelper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }    
    /**
     * 初始化
     */
    private void init() {        
        //创建ViewDragHelper的实例,第一个参数是ViewGroup,传自己,
        // 第二个参数就是滑动灵敏度的意思,可以随意设置,第三个是回调
        mViewDragHelper = ViewDragHelper.create(this, 1.0f, new DragHelperCallback());        
        //手势操作,第二参数什么意思看下面
        mGestureDetectorCompat = new GestureDetectorCompat(getContext(), new XScrollDetector());
    }    
     /**
     * 手势监听回调,
     * SimpleOnGestureListener为了不用重写那么多监听的帮助类
     */
    private class XScrollDetector extends GestureDetector.SimpleOnGestureListener {        
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,                                
        float distanceX, float distanceY) {            
        //判断是否是滑动的x距离>y距离
        return Math.abs(distanceY) <= math.abs(distancex);="" }="" draghelpercallback="" extends="" viewdraghelper.callback="" {="" **="" *="" 根据返回结果决定当前child是否可以拖拽="" @param="" child="" 当前被拖拽的view="" pointerid="" 区分多点触摸的id="" @return="" @override="" public="" boolean="" trycaptureview(view="" child,="" int="" pointerid)="" return="" mcontentlayout="=" child;="" 返回拖拽的范围,不对拖拽进行真正的限制,仅仅决定了动画执行速度="" getviewhorizontaldragrange(view="" child)="" mcontentlayoutwidth;="" left="" 代表你将要移动到的位置的坐标,返回值就是最终确定的移动的位置,="" 判断如果这个坐标在layout之内,那我们就返回这个坐标值,="" 不能让他超出这个范围,="" 除此之外就是如果你的layout设置了padding的话,="" 让子view的活动范围在padding之内的="" dx="" clampviewpositionhorizontal(view="" left,="" dx)="" log.d("wxl",="" "clampviewpositionhorizontal="" wxl",="" "onviewpositionchanged="" https:="" lc-api-gold-cdn.xitu.io="" 1879d45f418df3034f52"="" style="">