右滑退出SwipeBackLayout

    xiaoxiao2026-02-27  8

    参考了下网上大神们的思路,自己写了一套代码

    实现原理:

    1:自定义一个SwipeBackLayout,负责监听滑动事件和事件拦截。

    2:新建SwipeBackActivity,负责把SwipeBackLayout 把SwipeBackActivity插入decorView 与decorView的子View之间

    3:若按下坐标在屏幕最左侧且滑动方向为向右则拦截,并对SwipeBackLayout的内容进行滑动,当ACTION_UP时滑动距离超过屏幕4分之1则finish;

    代码:

    import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.Scroller; public class SwipeBackLayout extends FrameLayout { private int downX; private int downY; private int tempX; private Scroller mScroller; private int viewWidth; private boolean isSilding; private boolean isFinish; private boolean leftSlide;//是否是从左边边沿按下的 private Drawable mShadowDrawable; private Activity mActivity; public SwipeBackLayout(Context context) { this(context, null, 0); } public SwipeBackLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SwipeBackLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mScroller = new Scroller(context); // mShadowDrawable = getResources().getDrawable(R.drawable.shadow_left);用于绘制左侧遮罩背景 } public void attachToActivity(Activity activity) { mActivity = activity; ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView(); ViewGroup decorChild = (ViewGroup) decor.getChildAt(0); decor.removeView(decorChild); addView(decorChild); decor.addView(this); } /** * 事件拦截操作 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downX = tempX = (int) ev.getRawX(); downY = (int) ev.getRawY(); if(downX<10) leftSlide=true; break; case MotionEvent.ACTION_MOVE: int moveX = (int) ev.getRawX(); // 满足此条件屏蔽SildingFinishLayout里面子类的touch事件 if (downX<10&&moveX - downX > Math.abs((int) ev.getRawY() - downY) ) { return true; } break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { if(!leftSlide) return false; switch (event.getAction()) { case MotionEvent.ACTION_MOVE: int moveX = (int) event.getRawX(); int deltaX = tempX - moveX; tempX = moveX; if (moveX - downX >Math.abs((int) event.getRawY() - downY)) { isSilding = true; } if (moveX - downX >= 0 && isSilding) { this.scrollBy(deltaX, 0); } break; case MotionEvent.ACTION_UP: leftSlide=false; isSilding = false; if (this.getScrollX() <= -viewWidth / 4) { isFinish = true; scrollRight(); } else { scrollOrigin(); isFinish = false; } break; } return true; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (changed) { viewWidth = this.getWidth(); } } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); if (mShadowDrawable != null && this != null) { int left = this.getLeft() - mShadowDrawable.getIntrinsicWidth(); int right = left + mShadowDrawable.getIntrinsicWidth(); int top = this.getTop(); int bottom = this.getBottom(); mShadowDrawable.setBounds(left, top, right, bottom); mShadowDrawable.draw(canvas); } } /** * 滚动出界面 */ private void scrollRight() { final int delta = (viewWidth + this.getScrollX()); // 调用startScroll方法来设置一些滚动的参数,我们在computeScroll()方法中调用scrollTo来滚动item mScroller.startScroll(this.getScrollX(), 0, -delta + 1, 0, Math.abs(delta)); postInvalidate(); } /** * 滚动到起始位置 */ private void scrollOrigin() { int delta = this.getScrollX(); mScroller.startScroll(this.getScrollX(), 0, -delta, 0, Math.abs(delta)); postInvalidate(); } @Override public void computeScroll() { // 调用startScroll的时候scroller.computeScrollOffset()返回true, if (mScroller.computeScrollOffset()) { this.scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); if (mScroller.isFinished() && isFinish) { mActivity.finish(); } } } } import android.app.Activity; import android.content.Intent; import android.os.Bundle; public class SwipeBackActivity extends Activity { protected SwipeBackLayout layout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); layout = new SwipeBackLayout(this); layout.attachToActivity(this); } @Override public void startActivity(Intent intent) { super.startActivity(intent); //可以添加Activity进入退出的动画效果 // overridePendingTransition(R.anim.base_slide_right_in, R.anim.base_slide_remain); } // Press the back button in mobile phone @Override public void onBackPressed() { super.onBackPressed(); // overridePendingTransition(0, R.anim.base_slide_right_out); } }

    使用步骤:

    1:复制SwipeBackLayout,SwipeBackActivity代码

    2:对需要右滑退出的Activity继承SwipeBackActivity,并设置theme为@android:style/Theme.Translucent

    注意事件:

    1:mainActivity的theme不要为@android:style/Theme.Translucent,否则其他activity滑动的时间背景会是桌面 2:继承SwipeBackActivity的类requestWindowFeature等方法应该放在super.onCreate(savedInstanceState);之前 3:若不能直接继承SwipeBackActivity,也可不继承,直接在setContentView之前调用new SwipeBackLayout(this).attachToActivity(this);即可

    4:若发现当前Activity与上一个Activity界面重叠在一起了,只要给当前Activity加个背景即可

    转载请注明原文地址: https://ju.6miu.com/read-1307425.html
    最新回复(0)