侧滑退出

这个不是库,使用步骤如下:

1.AndroidManifest.xml文件里给Activity添加theme主题
<activity
    android:name=".NextActivity"
    android:theme="@style/AppTheme.Translucent.NoTitleBar">
</activity>

2.styles.xml文件添加主题//以下这两个主题效果一样,不知道为啥
<style name="AppTheme.Translucent">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:colorBackgroundCacheHint">@null</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowAnimationStyle">@android:style/Animation.Activity</item>
</style>

<style name="AppTheme.Translucent.NoTitleBar">
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowContentOverlay">@null</item>
</style>

3.Application注册Activity生命周期函数
registerActivityLifecycleCallbacks(ActivityLifeHelper.instance());

4.在需要滑动的Activity添加如下代码,如果整体App都需要的话,可以在自定义的BaseActivity添加
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    boolean processTouchEvent = SwipeHelper.instance().processTouchEvent(ev);
    if (processTouchEvent) {
        return true;
    }
    return super.dispatchTouchEvent(ev);
}

添加如下的类:
WindowHelper.java

public class WindowHelper {
    private static WindowHelper sWindowHelper;
    private int mScreenWidth;

    public static WindowHelper instance() {
        if (sWindowHelper == null) {
            synchronized (WindowHelper.class) {
                if (sWindowHelper == null) {
                    sWindowHelper = new WindowHelper();
                }
            }
        }
        return sWindowHelper;
    }

    public ViewGroup getDecorView(Activity activity) {
        if (activity == null) {
            return null;
        }
        return (ViewGroup) activity.getWindow().getDecorView();
    }

    public View getContentView(Activity activity) {
        ViewGroup decorView = getDecorView(activity);
        if (decorView == null) {
            return null;
        }
        return decorView.getChildAt(0);
    }

    //获取屏幕宽度
    public int getScreenWidth(Context context) {
        if (mScreenWidth == 0) {
            mScreenWidth = context.getResources().getDisplayMetrics().widthPixels;
        }
        return mScreenWidth;
    }
}

ActivityLifeHelper.java

public class ActivityLifeHelper extends BaseActivityLifecycle {

    private static ActivityLifeHelper sLifecycleHelper;
    private Stack<Activity> mActivityStack;

    private ActivityLifeHelper() {
        mActivityStack = new Stack<>();
    }

    public static ActivityLifeHelper instance() {
        if (sLifecycleHelper == null) {
            synchronized (ActivityLifeHelper.class) {
                if (sLifecycleHelper == null) {
                    sLifecycleHelper = new ActivityLifeHelper();
                }
            }
        }
        return sLifecycleHelper;
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        addActivity(activity);
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        removeActivity(activity);
    }

    /**
     * 添加Activity到堆栈
     */
    public void addActivity(Activity activity) {
        if (activity != null) {
            mActivityStack.add(activity);
        }
    }

    /**
     * 将Activity从堆栈移除
     * @param activity
     */
    public void removeActivity(Activity activity) {
        if (activity != null) {
            mActivityStack.remove(activity);
        }
    }

    /**
     * 获取当前Activity
     */
    public Activity getCurrentActivity() {
        Activity activity = mActivityStack.lastElement();
        return activity;
    }

    /**
     * 获取上一个Activity
     */
    public Activity getPreviewActivity() {
        int size = mActivityStack.size();
        if (size < 2) return null;
        return mActivityStack.elementAt(size - 2);
    }
}

BaseActivityLifecycle.java

public class BaseActivityLifecycle implements Application.ActivityLifecycleCallbacks {

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

    }

    @Override
    public void onActivityStarted(Activity activity) {

    }

    @Override
    public void onActivityResumed(Activity activity) {

    }

    @Override
    public void onActivityPaused(Activity activity) {

    }

    @Override
    public void onActivityStopped(Activity activity) {

    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

    }

    @Override
    public void onActivityDestroyed(Activity activity) {

    }
}

SwipeHelper.java

public class SwipeHelper {
    private final int START_SLIDE_X = 30;

    private static SwipeHelper sSwipeHelper;
    private float mDownX;//按下的位置
    private float mMoveX;//当前滑动位置
    private float mMaxMoveX;//最大的滑动位置
    private long mDownTime;//按下的时间点

    private float mScreenWidth;
    private float mPreContentViewX;//最大的前一个View的X位置,也就是在屏幕左侧的最大值

    private ValueAnimator mPreContentViewAnimator;
    private ValueAnimator mCurContentViewAnimator;

    private SwipeHelper() {
        mPreContentViewAnimator = ValueAnimator.ofFloat(0, 0);
        mPreContentViewAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        mPreContentViewAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Object value = animation.getAnimatedValue();
                View preContentView = getPreContentView();
                if (value instanceof Float && preContentView != null) {
                    float aFloat = Float.parseFloat(value.toString());
                    if (aFloat <= mPreContentViewX) {//说明滑动结束,恢复0值
                        aFloat = 0;
                    }
                    preContentView.setX(aFloat);
                }
            }
        });

        mCurContentViewAnimator = ValueAnimator.ofFloat(0, 0);
        mCurContentViewAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        mCurContentViewAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Object value = animation.getAnimatedValue();
                View curContentView = getCurContentView();
                if (value instanceof Float && curContentView != null) {
                    float aFloat = Float.parseFloat(value.toString());
                    curContentView.setX(aFloat);
                    if (aFloat >= mScreenWidth) {
                        ActivityLifeHelper.instance().getCurrentActivity().finish();
                    }
                }
            }
        });
    }

    public static SwipeHelper instance() {
        if (sSwipeHelper == null) {
            synchronized (WindowHelper.class) {
                if (sSwipeHelper == null) {
                    sSwipeHelper = new SwipeHelper();
                }
            }
        }
        return sSwipeHelper;
    }


    private View getCurContentView() {
        Activity curActivity = ActivityLifeHelper.instance().getCurrentActivity();
        if (curActivity != null) {
            return WindowHelper.instance().getContentView(curActivity);
        }
        return null;
    }

    private View getPreContentView() {
        Activity preActivity = ActivityLifeHelper.instance().getPreviewActivity();
        if (preActivity != null) {
            return WindowHelper.instance().getContentView(preActivity);
        }
        return null;
    }

    public boolean processTouchEvent(MotionEvent ev) {
        if (mCurContentViewAnimator.isRunning() || mPreContentViewAnimator.isRunning()) {
            return true;
        }

        View curContentView = getCurContentView();
        View preContentView = getPreContentView();
        if (curContentView == null || preContentView == null) {
            return false;
        }

        Activity curActivity = ActivityLifeHelper.instance().getCurrentActivity();
        if (mScreenWidth <= 0) {
            mScreenWidth = WindowHelper.instance().getScreenWidth(curActivity);
            mPreContentViewX = -mScreenWidth * 0.3f;
        }

        switch (ev.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                mDownX = ev.getX();
                if (mDownX > START_SLIDE_X) {
                    return false;//按下边缘位置才允许滑动
                }
                mDownTime = System.currentTimeMillis();
                preContentView.setX(mPreContentViewX);
                break;
            case MotionEvent.ACTION_MOVE:
                if (mDownX > START_SLIDE_X) {
                    return false;//按下边缘位置才允许滑动
                }
                mMoveX = ev.getX();
                if (mMoveX > mMaxMoveX) mMaxMoveX = mMoveX;
                if (mMoveX > (mScreenWidth - START_SLIDE_X / 2)) {//滑到最右端
                    preContentView.setX(0);
                    curActivity.finish();
                    return true;
                }
                //移动当前View
                float distance = mMoveX - mDownX;
                if (distance < 0) {
                    distance = 0;
                }
                curContentView.setX(distance);

                //移动之前View
                float preDistance = mPreContentViewX + distance / 3;
                if (preDistance > 0) {
                    preDistance = 0;
                }
                preContentView.setX(preDistance);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (mDownX > START_SLIDE_X) {
                    return false;//按下边缘位置才允许滑动
                }
                float upX = ev.getX();
                if (upX < mMaxMoveX && (mMaxMoveX - upX) / (System.currentTimeMillis() - mDownTime) > 0.1) {//快速向左滑动
                    animateCurContentView(curContentView.getX(), 0);
                    animatePreContentView(preContentView.getX(), mPreContentViewX);
                } else if ((upX - mDownX) / (System.currentTimeMillis() - mDownTime) > 0.5//快速向右滑动
                        || upX > mScreenWidth / 2) {//大于屏幕一半就结束当前Activity,根据自己需求而定吧
                    animateCurContentView(curContentView.getX(), mScreenWidth);
                    animatePreContentView(preContentView.getX(), 0);
                } else {
                    animateCurContentView(curContentView.getX(), 0);
                    animatePreContentView(preContentView.getX(), mPreContentViewX);
                }
                mMaxMoveX = 0;
                break;
        }
        return true;
    }

    private void animatePreContentView(float start, float end) {
        mPreContentViewAnimator.setFloatValues(start, end);
        mPreContentViewAnimator.start();
    }

    private void animateCurContentView(float start, float end) {
        mCurContentViewAnimator.setFloatValues(start, end);
        mCurContentViewAnimator.start();
    }
}

参考文章:
https://github.com/yongfengnice/SwipeFinish

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,917评论 25 709
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,601评论 2 45
  • 在聽到蘇打綠《痛快的哀艷》的時候,講真我是什麼都聽不懂的,因此也沒有深入的瞭解。之後在《冬 未了》這張專輯的其他歌...
    孤束阅读 158评论 0 0
  • 有人神化它,用影像不断诉说它的传奇故事;有人对它不屑一顾,认为它只不过是公园里老人们的另一种"广场舞"。太极拳正处...
    夏耶阅读 763评论 0 1
  • “肉体是拿来用的,不是拿来伺候的”最早听到《皮囊》是韩寒做的“一个”中推的,前年或前几年吧。直到十一前无意看到这本...
    介甲阅读 319评论 0 0