高仿QQ6.0侧滑菜单之滑动优化(二)

好了,昨天已经实现了高仿QQ6.0的侧滑大致框架,如有兴趣,可以去看下仿QQ6.0侧滑之ViewDragHelper的使用(一)
但是之前的实现,只是简单的可以显示和隐藏左侧的菜单,但是特别生硬,而且没有任何平滑的趋势,那么今天就来优化一下吧,加上平滑效果,而且可以根据手势滑动的方向来判断是否是显示和隐藏。

首先先来实现手势判断是否隐藏和显示

这里就要用到了一个方法了,如下:
这个是ViewDradHelper里面的方法:

/** * 当view被释放的时候处理的事情(松手) * * @param releasedChild 被释放的子view * @param xvel 水平方向的速度 帧每秒 向右为 + * @param yvel 竖直方向的速度 向下为 + */
        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            Log.d("DragLayout", "xvel : " + xvel + " yvel :" + yvel);
            super.onViewReleased(releasedChild, xvel, yvel);

            //判断关闭和打开
            //在这里我们首先判断什么时候打开,然后剩下的都是关闭状态
            //首先是我的主面板的左侧具体屏幕左侧已经大于mRange/2的距离并且右滑的速度大于0,此时打开
            if (xvel >= 0 && mMainContent.getLeft() > mRange / 2.0f) {
                open();
            } else if (xvel > 0) {
                //第二种就是我右滑的速度大于0(这里的速度自己定义哈,根据自己想要实现的敏感度)
                open();
            } else {
                //剩余的所有情况都是关闭
                close();
            }

        }

close()方法(DragLayout里面的方法):


    /** * 关闭 */
    public void close() {
        int finalLeft = 0;
        //调用layout方法,摆放主布局
        /** * @param l Left position, relative to parent * @param t Top position, relative to parent * @param r Right position, relative to parent * @param b Bottom position, relative to parent */
        mMainContent.layout(finalLeft, 0, finalLeft + mWidth, finalLeft + mHeight);

    }

open()方法(DragLayout里面的方法):

/** * 打开 */
    public void open() {
        int finalLeft = mRange;
        mMainContent.layout(finalLeft, 0, finalLeft + mWidth, finalLeft + mHeight);
    }

这个是否就可以实现根据手势来判断是否打开和关闭了。

接下来我们就来实现如何平滑的关闭和打开,话不多说,代码说话(这里对上面的open和close做了一些处理):
 public void close() {
        close(true);
    }

    /** * 关闭 * * @param isSmooth 是否平滑的关闭 */
    public void close(boolean isSmooth) {
        int finalLeft = 0;

        if (isSmooth) {
            /** * public boolean smoothSlideViewTo(View child, int finalLeft, int finalTop)方法的解释 * * Animate the view <code>child</code> to the given (left, top) position. * If this method returns true, the caller should invoke {@link #continueSettling(boolean)} * on each subsequent frame to continue the motion until it returns false. If this method * returns false there is no further work to do to complete the movement. * * 返回true 代表还没有移动到指定的位置,需要刷新界面,继续移动 * 返回false 就停止工作哈 */
            //1、触发动画
            if (mDragHelper.smoothSlideViewTo(mMainContent, finalLeft, 0)) {
                //参数传this,也就是child所在的viewgroup
                ViewCompat.postInvalidateOnAnimation(this);
            }
        } else {

            //调用layout方法,摆放主布局
            /** * @param l Left position, relative to parent * @param t Top position, relative to parent * @param r Right position, relative to parent * @param b Bottom position, relative to parent */
            mMainContent.layout(finalLeft, 0, finalLeft + mWidth, finalLeft + mHeight);
        }

    }

    /** * 打开 */
    public void open(boolean isSmooth) {
        int finalLeft = mRange;

        if (isSmooth && mDragHelper.smoothSlideViewTo(mMainContent, finalLeft, 0)) {
            //参数传this,也就是child所在的viewgroup
            ViewCompat.postInvalidateOnAnimation(this);
        } else {
            mMainContent.layout(finalLeft, 0, finalLeft + mWidth, finalLeft + mHeight);
        }
    }

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

来看下效果图吧(里面的白道问题是录屏导致,运行的没有这个哈):

这个时候,基本上差不多了,剩下的,我们就来添加一些状态和设置listener的方法,留给外面的调用吧。,代码很简单:

/** * 定义当前状态 默认是关闭状态 */
    private Status mStatus = Status.CLOSE;


    /** * 状态枚举 * 关闭 CLOSE * 打开 OPEN * 拖拽 DRAGING */
    public enum Status {
        CLOSE, OPEN, DRAGING;
    }

    private OnDragStatusListener mListener;


    public void setDragStateListener(OnDragStatusListener listener) {
        mListener = listener;
    }

    public interface OnDragStatusListener {

        /** * 关闭逻辑 */
        void onClose();

        /** * 打开逻辑 */
        void onOpen();

        /** * 拖拽逻辑 * * @param percent */
        void onDraging(float percent);
    }

状态更新,方法调用,这个dispatchDragEvent()在onViewPositionChanged()这个方法中调用一下就行,因为拖拽的时候状态时刻在变化,所以我们在这个方法中调用:

 /** * 状态更新方法执行 * * @param newLeft */
    private void dispatchDragEvent(int newLeft) {
        //得到的一个百分比
        float percent = newLeft * 1.0f / mRange;

        //0.0f--->1.0f
        Log.d("DragLayout", "percent : " + percent);

        if (mListener != null) {
            mListener.onDraging(percent);
        }

        //跟新状态执行回调
        Status lastStatus = mStatus;

        mStatus = updateStatus(percent);

        if (mStatus != lastStatus) {
            //状态发生变化
            if (mStatus == Status.CLOSE) {
                //当前状态是关闭
                if (mListener != null) {
                    mListener.onClose();
                }
            } else if (mStatus == Status.OPEN) {
                if (mListener != null) {
                    mListener.onOpen();
                }
            }
        }

    }

    /** * 状态更新方法 * * @param percent * @return */
    private Status updateStatus(float percent) {
        if (percent == 0) {
            return Status.CLOSE;
        } else if (percent == 1) {
            return Status.OPEN;
        }
        return Status.DRAGING;
    }

好了,到此为止,高仿QQ6.0侧滑基本完成,下面我们来看下效果吧。
高仿QQ6.0侧滑菜单之滑动优化(二)_第1张图片
好了,这个侧滑就这样完成了,后期会加在主页中加入listview(尝试用RecycleView)实现左滑删除效果,现在附上该demo的地址,后期添加的也会更新至此。
本项目的github地址:https://github.com/wuyinlei/QQ6.0
如有问题,或者交流的话,可以QQ:1069584784。

你可能感兴趣的:(高仿QQ6.0侧滑菜单之滑动优化(二))