1. 程式人生 > >實現Activity側滑返回效果

實現Activity側滑返回效果

先看一張效果圖

這裡寫圖片描述

通過ViewDragHelper來檢測到螢幕側滑,然後通過內建介面傳遞給Acitivity觸發了側滑事件,通知其關閉。

1、實現側滑刪除,這裡的方法是先要建立一個監聽側滑的自定義佈局.

public class SwipeBackLayout extends FrameLayout {
    private ViewDragHelper mViewDragHelper;
    private View mContentView;
    private int mContentWidth;
    private boolean isClose;
    private
int mMoveLeft; private callBackListener mCallBackListener; public SwipeBackLayout(Context context) { this(context, null); } public SwipeBackLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SwipeBackLayout(Context context, AttributeSet attrs, int
defStyleAttr) { super(context, attrs, defStyleAttr); mViewDragHelper = ViewDragHelper.create(this, new ViewDragHelperCallBack()); } @Override public boolean onTouchEvent(MotionEvent event) { mViewDragHelper.processTouchEvent(event); return true; } @Override
protected void onFinishInflate() { super.onFinishInflate(); mContentView = getChildAt(0); } protected void setCallBackListener(callBackListener callBackListener) { this.mCallBackListener = callBackListener; } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); mContentWidth = this.getWidth(); } class ViewDragHelperCallBack extends ViewDragHelper.Callback { //tryCaptureView:捕捉View ---》移動那個View @Override public boolean tryCaptureView(View child, int pointerId) { return child == mContentView; } //設定水平拖動的距離 @Override public int getViewHorizontalDragRange(View child) { //因為我們移動的是整個介面,所以直接返回整個介面的寬度就可以了 return mContentWidth; } //記錄值的變化 @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { if (changedView == mContentView) { //記錄左邊的值的變化,因為我們實現的是往右滑動,所以只記錄左邊的值就可以了 mMoveLeft = left; if (isClose || mMoveLeft == mContentWidth) { //mMoveLeft==mContentWidth如果滑動的距離正好等於mContentWidth //也就是說當前的介面已經滑出螢幕,就回調finish方法,通知activity可以finish了 mCallBackListener.onFinish(); } } } @Override public int clampViewPositionHorizontal(View child, int left, int dx) { //水平移動距離的範圍是0~當前介面的寬度,如果left小於0直接返回0, // 如果大於當前介面的寬度直接返回當前介面寬度 //也就是控制當前介面只能往右移動 return Math.min(mContentWidth, Math.max(left, 0)); } //手指鬆開會觸發這個方法,做復位操作就在此方法中實現 @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { //如果移動的距離大於或等於當前介面的1/5,則觸發關閉 if (mMoveLeft >= (mContentWidth / 5)) { isClose = true; //設定滑動的View移動位置,即然當前的介面滑出螢幕 mViewDragHelper.settleCapturedViewAt(mContentWidth, releasedChild.getTop()); } else { //設定滑動的View移動位置,即恢復原來的位置 mViewDragHelper.settleCapturedViewAt(0, releasedChild.getTop()); } //通知重繪介面 ViewCompat.postInvalidateOnAnimation(SwipeBackLayout.this); } } //view剛初始化的時候就會被呼叫一次 @Override public void computeScroll() { if (mViewDragHelper.continueSettling(true)) { ViewCompat.postInvalidateOnAnimation(this); } } //回撥介面 protected interface callBackListener { void onFinish(); }

2 側滑返回的Activity進入和退出的動畫

    <!--設定Activity進入和退出的動畫-->
    <style name="SlideRightAnimation" parent="@android:style/Animation.Activity">
        <item name="android:activityOpenEnterAnimation">@anim/slide_in_right</item>
        <item name="android:activityOpenExitAnimation">@null</item>
        <item name="android:activityCloseEnterAnimation">@null</item>
        <item name="android:activityCloseExitAnimation">@anim/slide_out_right</item>
        <item name="android:taskOpenEnterAnimation">@anim/slide_in_right</item>
        <item name="android:taskOpenExitAnimation">@null</item>
        <item name="android:taskCloseEnterAnimation">@null</item>
        <item name="android:taskCloseExitAnimation">@anim/slide_out_right</item>
        <item name="android:taskToFrontEnterAnimation">@anim/slide_in_right</item>
        <item name="android:taskToFrontExitAnimation">@null</item>
        <item name="android:taskToBackEnterAnimation">@null</item>
        <item name="android:taskToBackExitAnimation">@anim/slide_out_right</item>
    </style>

slide_in_right.xml

<?xml version="1.0" encoding="utf-8"?>
<translate  xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="250"
    android:fromXDelta="100%p"
    android:toXDelta="0"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator">
</translate>

slide_out_right.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="250"
    android:fromXDelta="0"
    android:toXDelta="100%p"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator">
</translate>
  <style name="AppTheme.TransparentActivity" parent="Theme.AppCompat.NoActionBar">
        <!--設定滑動的Activity背景透明-->
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowIsTranslucent">true</item>
        <!-- android:windowAnimationStyle引入動畫 -->
        <item name="android:windowAnimationStyle">@style/SlideRightAnimation</item>
    </style>

3 設定滑動的Activity的主題為AppTheme.TransparentActivity

  <activity
            android:name=".SwipeBack.SwipeBackActivity"
            android:theme="@style/AppTheme.TransparentActivity">

        </activity>

實現這個功能主要是要知道自定義ViewGroup神器ViewDragHelper的用法和Activity進入和退出的動畫是怎麼設定的;其次的需要設定滑動的Activity背景透明,通過內建介面傳遞給Acitivity觸發了側滑事件,通知其關閉。