美文网首页Android
Android数行代码实现仿QQ右滑手势返回

Android数行代码实现仿QQ右滑手势返回

作者: woxingxiao | 来源:发表于2017-10-23 17:05 被阅读44次

    右滑结束当前界面返回上一界面,是一个很棒的交互,尤其对大屏幕手机用户。iOS原生可以完美地支持,Android原生却并未得到支持。支持右滑返回的开源项目五花八门,然而或多或少有配置麻烦、兼容适配、性能开销等问题。但是,如果你单纯想实现一个滑动返回,而不需要各种效果,就像手机QQ那样,那么请往下看。

    原理

    捕捉Activity触摸事件分发,判断右滑手势,结束当前界面。
    一般而言,当手机触摸屏幕那一刻,首先由Activity的dispatchTouchEvent()开始向下分发事件,各ViewGroup再分发至其子View。因此,我们重写Activity的dispatchTouchEvent()方法,在其中判断用户是否进行了有效的右滑操作(但不能改变其固有的分发逻辑),从而结束当前Activity。

    关于Android的事件分发机制不在此展开,张神的这篇博文我觉得是讲得非常通俗易懂的。

    实现

    为了write once, use anywhere,我们可以写到BaseActivity里,需要右滑返回的界面继承之即可。

    public abstract class BaseActivity extends AppCompatActivity {
    
        private MotionEvent mActionDownEvent;
        private VelocityTracker mVelocityTracker;
    
        ......
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            if (mVelocityTracker == null) {
                mVelocityTracker = VelocityTracker.obtain();
            }
            mVelocityTracker.addMovement(ev);
    
            if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
                if (mActionDownEvent != null) {
                    mActionDownEvent.recycle();
                }
                mActionDownEvent = MotionEvent.obtain(ev);  // 记录按下时的事件
            } else if (ev.getActionMasked() == MotionEvent.ACTION_UP) {
                // 右滑返回手势检测
                int pointerId = ev.getPointerId(0);
                int maximumFlingVelocity = ViewConfiguration.get(this).getScaledMaximumFlingVelocity();
                int minimumFlingVelocity = ViewConfiguration.get(this).getScaledMinimumFlingVelocity();
                mVelocityTracker.computeCurrentVelocity(1000, maximumFlingVelocity);
                final float velocityX = mVelocityTracker.getXVelocity(pointerId);
    
               if (mActionDownEvent.getX() <= 50  // 左边缘检测,可根据需要调整,单位像素
                        && ev.getX() - mActionDownEvent.getX() >= 300  // 有效触发距离,可根据需要调整,单位像素
                        && Math.abs(velocityX) >= minimumFlingVelocity) {
                    onBackPressed(); // finish当前Activity
                }
            }
    
            return super.dispatchTouchEvent(ev);  // 分发控制还给Activity
        }
    
        ......
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
    
            if (mVelocityTracker != null) {
                mVelocityTracker.recycle();
            }
        }
    }
    

    没错,就这么简单!
    如果想实现自由的开关滑动返回功能,只需要加一个开关参数即可:

        boolean disableSlidingBack; // 在子Activity中设为true,关闭滑动返回
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
        if (disableSlidingBack) {
            return super.dispatchTouchEvent(ev);
        }
        // 后面不变
        }
    

    效果

    实际效果动画

    图中Activity finish过渡没有使用动画,是系统自带的效果。我的系统是MIUI,部分系统过渡动画可能不是左右方向,如果考虑适配问题,可以在style里统一设置。

    相关文章

      网友评论

        本文标题:Android数行代码实现仿QQ右滑手势返回

        本文链接:https://www.haomeiwen.com/subject/aeoouxtx.html