實現Activity側滑返回效果
阿新 • • 發佈:2018-12-17
先看一張效果圖
通過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觸發了側滑事件,通知其關閉。