Activity右滑退出控件SlidingLayout

在Android开发中,我们可能会想使用和IOS一样右滑退出界面的效果,在这里,我为大家提供一种快速使用的控件-SlidingLayout下面是使用后的效果

Activity右滑退出控件SlidingLayout_第1张图片
SlidingLayout.java

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()方法失效

你可能感兴趣的:(Activity右滑退出控件SlidingLayout)