zoukankan      html  css  js  c++  java
  • 高仿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的方法,留给外面的调用吧。。代码非常easy:

    /**
         * 定义当前状态  默认是关闭状态
         */
        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側滑基本完毕。以下我们来看下效果吧。
    这里写图片描写叙述
    好了,这个側滑就这样完毕了。后期会加在主页中加入listview(尝试用RecycleView)实现左滑删除效果,如今附上该demo的地址,后期加入的也会更新至此。


    本项目的github地址:https://github.com/wuyinlei/QQ6.0
    如有问题。或者交流的话,能够QQ:1069584784。

  • 相关阅读:
    About Dump File
    设置IIS延长Debug
    正则表达式中\d和[00]有什么区别
    理解程序语言语法的merge工具——semanticmerge
    大数据还是小数据
    如何在TFS中配置别的diff/merge的工具
    一个很cool的展示编程语言相互影响关系的网状图
    常见的算法的时间和空间复杂度
    C#的强迫执行域Constrained Execution Regions(CERs)
    C++的C4305和C4800的编译警告
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7233150.html
Copyright © 2011-2022 走看看