ViewDragHelper实现微信侧滑

本文是参考开源的代码进行修改获得的,https://github.com/BlueMor/DragLayout

 具体实现已经都在代码中添加了注解,


public class SlideDrawLayout extends FrameLayout {

    private Context mContext;

    private View mLeftContainer;

    private View mMainContainer;

    private ViewDragHelper dragHelper;

    private int mDragTotalDis;


    private int mMainToLeftDis; // 就记录主View的左边距离

    private int mWidth;

    private int mHeight;

    private int mLeftWidth;

    private int mLeftLayoutDis;

    private int mLeftScrollDis;

    public SlideDrawLayout(Context context) {
        this(context, null, -1);
    }

    public SlideDrawLayout(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public SlideDrawLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    public void init(Context context) {

        mContext = context;

        // 第二参数,配置拖动的敏感度
        dragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {

            //决定chlid是否可被拖动
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                return child == mLeftContainer || child == mMainContainer;
            }

            // 当View正被拖着时
            @Override
            public void onViewCaptured(View capturedChild, int activePointerId) {
                super.onViewCaptured(capturedChild, activePointerId);
            }

            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                if (releasedChild == mMainContainer) {
                    if (mMainToLeftDis > mDragTotalDis / 3) {
                        open();
                    } else {
                        close();
                    }
                } else if (releasedChild == mLeftContainer) {
                    if (mMainToLeftDis < mDragTotalDis / 3) {
                        close();
                    } else {
                        open();
                    }
                }
            }

            // 横向拖拽的范围,大于0时可拖拽,等于0无法拖拽
            // 此方法只用于计算如view释放速度,敏感度等
            // 实际拖拽范围由clampViewPositionHorizontal方法设置
            @Override
            public int getViewHorizontalDragRange(View child) {
                return super.getViewHorizontalDragRange(child);
            }

            //返回的是拖动的范围,如果当前移动的超过了,不能继续拖动
            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                if (mMainToLeftDis + dx < 0) {
                    return 0;
                } else if (mMainToLeftDis + dx > mDragTotalDis) {
                    return mDragTotalDis;
                }
                return left;
            }

            // 当View位置发生变化,
            @Override
            public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
                if (changedView == mMainContainer) {
                    mMainToLeftDis = left;
                } else {// 当是左边的View时, left,就是左边View的值了,
                    mMainToLeftDis += dx;
                }

                // 进行值的修正
                if (mMainToLeftDis < 0) {
                    mMainToLeftDis = 0;
                } else if (mMainToLeftDis > mDragTotalDis) {
                    mMainToLeftDis = mDragTotalDis;
                }

                // 如果拖拽的是左面板,强制在指定位置绘制Content
                if (changedView == mLeftContainer) {
                    layoutContent();
                }

                dispatchDragEvent(mMainToLeftDis);

            }

            @Override
            public int clampViewPositionVertical(View child, int top, int dy) {
                return super.clampViewPositionVertical(child, top, dy);
            }


        });
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return dragHelper.shouldInterceptTouchEvent(ev);
    }

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

    private void layoutContent() {
        mMainContainer.layout(mMainToLeftDis, 0, mMainToLeftDis + mWidth, mHeight);
        mLeftContainer.layout(0, 0, mWidth, mHeight);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

        mMainContainer.layout(mMainToLeftDis, 0, mMainToLeftDis + mWidth, mHeight);
        mLeftContainer.layout(0, 0, mLeftWidth, mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 初始移动一定距离
        ViewHelper.setTranslationX(mLeftContainer, -mLeftLayoutDis);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();

        if (mLeftContainer != null) {

            mLeftWidth = mLeftContainer.getMeasuredWidth();

            mLeftLayoutDis = mLeftWidth / 3;

            mDragTotalDis = mLeftWidth;

            mLeftScrollDis = mLeftLayoutDis;

        }

    }

    /**
     * 每次更新都会调用 根据当前执行的位置计算百分比percent
     */
    protected void dispatchDragEvent(int left) {
        float percent = left / (float) mDragTotalDis;
        animViews(percent);
    }

    /**
     * 伴随动画:
     *
     * @param percent
     */
    private void animViews(float percent) {

        float leftDis = -mLeftScrollDis + mLeftScrollDis * percent;

        ViewHelper.setTranslationX(mLeftContainer, leftDis);
    }

    public void close() {
        close(true);
    }

    public void open() {
        open(true);
    }

    public void close(boolean isSmooth) {
        mMainToLeftDis = 0;
        if (isSmooth) {
            // 执行动画,返回true代表有未完成的动画, 需要继续执行
            if (dragHelper.smoothSlideViewTo(mMainContainer, mMainToLeftDis, 0)) {
                // 注意:参数传递根ViewGroup
                ViewCompat.postInvalidateOnAnimation(this);
            }
        } else {
            layoutContent();
        }
    }

    public void open(boolean isSmooth) {
        mMainToLeftDis = mDragTotalDis;
        if (isSmooth) {
            if (dragHelper.smoothSlideViewTo(mMainContainer, mMainToLeftDis, 0)) {
                ViewCompat.postInvalidateOnAnimation(this);
            }
        } else {
            layoutContent();
        }
    }

    @Override
    public void computeScroll() {
        //
        if (dragHelper.continueSettling(true)) { // true 决定后面继续执行,
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }

    /**
     * 填充结束时获得两个子布局的引用
     */
    @Override
    protected void onFinishInflate() {

        super.onFinishInflate();

        int childCount = getChildCount();
        // 必要的检验
        if (childCount < 2) {
            throw new IllegalStateException(
                    "You need two childrens in your content");
        }

        if (!(getChildAt(0) instanceof ViewGroup)
                || !(getChildAt(1) instanceof ViewGroup)) {
            throw new IllegalArgumentException(
                    "Your childrens must be an instance of ViewGroup");
        }

        mLeftContainer = getChildAt(0);
        mMainContainer = getChildAt(1);

    }
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值