Android

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

2017-10-23  本文已影响44人  woxingxiao

右滑结束当前界面返回上一界面,是一个很棒的交互,尤其对大屏幕手机用户。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里统一设置。

上一篇下一篇

猜你喜欢

热点阅读