在Android开发中,我们可能会想使用和IOS一样右滑退出界面的效果,在这里,我为大家提供一种快速使用的控件-SlidingLayout下面是使用后的效果
public class SlidingLayout extends FrameLayout {
private static final int SHADOW_WIDTH = 16;
private Activity mActivity;
private Scroller mScroller;
private Drawable mLeftShadow;
private int mShadowWidth;
private int mInterceptDownX;
private int mLastInterceptX;
private int mLastInterceptY;
private int mTouchDownX;
private int mLastTouchX;
private int mLastTouchY;
private boolean isConsumed;
public SlidingLayout(Context context) {
this(context, (AttributeSet)null);
}
public SlidingLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidingLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.isConsumed = false;
this.initView(context);
}
private void initView(Context context) {
this.mScroller = new Scroller(context);
this.mLeftShadow = this.getResources().getDrawable(R.drawable.left_shadow);
int density = (int)this.getResources().getDisplayMetrics().density;
this.mShadowWidth = 16 * density;
}
public void bindActivity(Activity activity) {
this.mActivity = activity;
ViewGroup decorView = (ViewGroup)this.mActivity.getWindow().getDecorView();
View child = decorView.getChildAt(0);
decorView.removeView(child);
this.addView(child);
decorView.addView(this);
}
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercept = false;
int x = (int)ev.getX();
int y = (int)ev.getY();
switch(ev.getAction()) {
case 0:
intercept = false;
this.mInterceptDownX = x;
this.mLastInterceptX = x;
this.mLastInterceptY = y;
break;
case 1:
intercept = false;
this.mInterceptDownX = this.mLastInterceptX = this.mLastInterceptY = 0;
break;
case 2:
int deltaX = x - this.mLastInterceptX;
int deltaY = y - this.mLastInterceptY;
if(this.mInterceptDownX < this.getWidth() / 10 && Math.abs(deltaX) > Math.abs(deltaY)) {
intercept = true;
} else {
intercept = false;
}
this.mLastInterceptX = x;
this.mLastInterceptY = y;
}
return intercept;
}
public boolean onTouchEvent(MotionEvent ev) {
int x = (int)ev.getX();
int y = (int)ev.getY();
switch(ev.getAction()) {
case 0:
this.mTouchDownX = x;
this.mLastTouchX = x;
this.mLastTouchY = y;
break;
case 1:
this.isConsumed = false;
this.mTouchDownX = this.mLastTouchX = this.mLastTouchY = 0;
if(-this.getScrollX() < this.getWidth() / 2) {
this.scrollBack();
} else {
this.scrollClose();
}
break;
case 2:
int deltaX = x - this.mLastTouchX;
int deltaY = y - this.mLastTouchY;
if(!this.isConsumed && this.mTouchDownX < this.getWidth() / 10 && Math.abs(deltaX) > Math.abs(deltaY)) {
this.isConsumed = true;
}
if(this.isConsumed) {
int rightMovedX = this.mLastTouchX - (int)ev.getX();
if(this.getScrollX() + rightMovedX >= 0) {
this.scrollTo(0, 0);
} else {
this.scrollBy(rightMovedX, 0);
}
}
this.mLastTouchX = x;
this.mLastTouchY = y;
}
return true;
}
private void scrollBack() {
int startX = this.getScrollX();
int dx = -this.getScrollX();
this.mScroller.startScroll(startX, 0, dx, 0, 300);
this.invalidate();
}
private void scrollClose() {
int startX = this.getScrollX();
int dx = -this.getScrollX() - this.getWidth();
this.mScroller.startScroll(startX, 0, dx, 0, 300);
this.invalidate();
}
public void computeScroll() {
if(this.mScroller.computeScrollOffset()) {
this.scrollTo(this.mScroller.getCurrX(), 0);
this.postInvalidate();
} else if(-this.getScrollX() >= this.getWidth()) {
this.mActivity.finish();
}
}
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
this.drawShadow(canvas);
}
private void drawShadow(Canvas canvas) {
this.mLeftShadow.setBounds(0, 0, this.mShadowWidth, this.getHeight());
canvas.save();
canvas.translate((float)(-this.mShadowWidth), 0.0F);
this.mLeftShadow.draw(canvas);
canvas.restore();
}
}
然后在使用的时候,放置在BaseActivity上
@Override
public final void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
************
if (enableSlideClose()) {//右滑退出
SlidingLayout rootView = new SlidingLayout(this);
rootView.bindActivity(this);
}
************
}
在BaseActivity上再写一个抽象方法
public boolean enableSlideClose() {
return true;
}
默认使用右滑退出Activity
我们再使用的过程中,可以在子类中复写enableSlideClose()方法,设置不使用右滑退出
子类extends BaseActivity
@Override
public boolean enableSlideClose() {
return false;
}
这样以后就可以右滑退出了
我们在使用过程中,可能会出现白色背景或者黑色背景闪现的可能性,这是由于未设置背景透明的原因,在这里,我们需要这样设置
-- Base application theme. -->
--右滑返回并退出Activity会有一个白色的背景出现,需要设置透明色-->
anim_slide_in.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="100%p"
android:toXDelta="0" />
set>
anim_slide_out.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="0"
android:toXDelta="100%p" />
set>
在清单文件中这样配置
".app.AichebabaApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme.Slide">
android:theme=”@style/AppTheme.Slide”
这样以后,就不会有其他白色背景或者黑色背景一闪而过的情况了。
注意:在设置
<item name="android:windowIsTranslucent">trueitem>
以后,这个Activity的栈中上一个Activity不会调用onRestart()方法,具体可以参考我的另一篇博客使用右滑退出界面时,onRestart()方法失效