首页 > 学院 > 开发设计 > 正文

滑动退出Activity的两种方法

2019-11-09 15:49:27
字体:
来源:转载
供稿:网友

最近遇到需求,需要滑动退出Activity,参考了大虾们的方案后整理出了两种主流的方法:

使用OnTouchEvent,处理触摸事件实现滑动退出使用ViewDragHelper拖动实现滑动退出

两种方法各有利弊,遇到界面上的滑动或滚动事件产生冲突的需要自己处理,下面就来详细的介绍两种实现方法。

0.前提

两种方法不管使用哪一种都需要设置透明主题及Activity中根布局的background,以实现滑动时,上一个Activity可见。

Activity根布局背景: android:background="?android:colorBackground"Activity主题: <style name="Translucent" parent="APPTheme"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowAnimationStyle">@android:style/Animation</item> </style>

1.使用OnTouchEvent,处理触摸事件实现滑动退出

先来看看具体实现:

/** * @author Steven Duan * @version 1.0 */public class SlideLayout extends FrameLayout { PRivate static final String T = SlideLayout.class.getName(); private Activity mActivity; private Scroller mScroller; private int mShadowWidth; private Drawable mLeftShadow; private int mLastMoveX; private int mScreenWidth; private int mMinX; public SlideLayout(Activity activity) { this(activity, null); } public SlideLayout(Activity activity, AttributeSet attrs) { this(activity, attrs, 0); } public SlideLayout(Activity activity, AttributeSet attrs, int defStyleAttr) { super(activity, attrs, defStyleAttr); Log.d(T, "F初始化 "); this.mActivity = activity; mScroller = new Scroller(activity); //滑动时渐变的阴影 //noinspection deprecation mLeftShadow = getResources().getDrawable(R.drawable.left_shadow); //阴影的宽度 mShadowWidth = ((int) getResources().getDisplayMetrics().density) * 16; } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastMoveX = (int) event.getX(); mScreenWidth = getWidth(); mMinX = mScreenWidth / 10; break; case MotionEvent.ACTION_MOVE: int eventX = (int) event.getX(); Log.d(T, "eventX: " + eventX); int dx = mLastMoveX - eventX; if (getScrollX() + dx >= 0) { scrollTo(0, 0); } else if (eventX > mMinX) { //手指处于屏幕边缘时不处理滑动 scrollBy(dx, 0); } mLastMoveX = eventX; break; case MotionEvent.ACTION_UP: if (-getScrollX() < mScreenWidth / 2) { slideBack(); } else { slideFinish(); } break; } return true; } private void slideFinish() { mScroller.startScroll(getScrollX(), 0, -getScrollX() - mScreenWidth, 0, 200); invalidate(); } private void slideBack() { mScroller.startScroll(getScrollX(), 0, -getScrollX(), 0, 200); invalidate(); } @Override public void computeScroll() { super.computeScroll(); if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), 0); postInvalidate(); } else if (-getScrollX() == mScreenWidth) { mActivity.finish(); } } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); //绘制边缘阴影 canvas.save(); //设置阴影的大小范围 mLeftShadow.setBounds(0, 0, mShadowWidth, getHeight()); //平移画布 canvas.translate(-mShadowWidth, 0); //绘制 mLeftShadow.draw(canvas); canvas.restore(); } public void bind() { Log.d(T, "bind: F"); ViewGroup decorView = (ViewGroup) mActivity.getWindow().getDecorView(); View child = decorView.getChildAt(0); decorView.removeView(child); addView(child); decorView.addView(this); Log.d(T, "bind成功"); }}

定义好了容器,那么在Activity中如何使用呢?只需要在Activity的onCreate方法做如下调用即可:

@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); new SlideLayout(this).bind(); }

代码比较简单,一看便知。只是这种方法在Activity中有滑动或滚动事件会产生冲突,这就涉及事件分发机制,需要自己看情况处理。

2.使用ViewDragHelper拖动实现滑动退出

废话不多说直接上代码:

/** * @author Steven Duan * @version 1.0 */public class SlideLayout extends FrameLayout { private View mDragView; private Activity mActivity; private ViewDragHelper mViewDragHelper; private float mSlideWidth; private int mScreenWidth; private int mScreenHeight; private int curSlideX; public SlideLayout(Context context) { super(context); init(context); } private void init(Context context) { mActivity = (Activity) context; mViewDragHelper = ViewDragHelper.create(this, new DragCallback()); //设置可拖动的边缘 mViewDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT); } /** * 把DecorView下的子View移除添加到SlideLayout,再将SlideLayout添加到DecorView */ public void bind() { ViewGroup mDecorView = (ViewGroup) mActivity.getWindow().getDecorView(); mDragView = mDecorView.getChildAt(0); mDecorView.removeView(mDragView); this.addView(mDragView); mDecorView.addView(this); //计算屏幕宽度 DisplayMetrics dm = new DisplayMetrics(); mActivity.getWindowManager().getDefaultDisplay().getMetrics(dm); mScreenWidth = dm.widthPixels; mScreenHeight = dm.heightPixels; //触发Activity滑出的宽度 mSlideWidth = dm.widthPixels * 0.5f; } @Override public boolean onInterceptHoverEvent(MotionEvent event) { return mViewDragHelper.shouldInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { mViewDragHelper.processTouchEvent(event); return true; } class DragCallback extends ViewDragHelper.Callback { @Override public boolean tryCaptureView(View child, int pointerId) { return false; } @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { int left = releasedChild.getLeft(); if (left <= mSlideWidth) { //返回 mViewDragHelper.settleCapturedViewAt(0, 0); } else { //滑出 mViewDragHelper.settleCapturedViewAt(mScreenWidth, 0); } //需要重绘 invalidate(); } @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { curSlideX = left; invalidate(); if (changedView == mDragView && left >= mScreenWidth) { mActivity.finish(); } } @Override public int clampViewPositionHorizontal(View child, int left, int dx) { //限制左右拖拽的位移 left = left >= 0 ? left : 0; return left; } @Override public int clampViewPositionVertical(View child, int top, int dy) { return 0; } @Override public void onEdgeDragStarted(int edgeFlags, int pointerId) { //触发边缘时,主动捕捉mDragView mViewDragHelper.captureChildView(mDragView, pointerId); } } @Override public void computeScroll() { //持续滚动期间,不断重绘 if (mViewDragHelper.continueSettling(true)) invalidate(); } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); //进行阴影绘制 canvas.save(); Shader mShader = new LinearGradient(curSlideX - 40, 0, curSlideX, 0, new int[]{Color.parseColor("#00000000"), Color.parseColor("#50000000")}, null, Shader.TileMode.REPEAT); //绘制阴影画笔 Paint mPaint = new Paint(); mPaint.setStrokeWidth(2); mPaint.setAntiAlias(true); mPaint.setColor(Color.GRAY); mPaint.setShader(mShader); RectF rectF = new RectF(curSlideX - 40, 0, curSlideX, mScreenHeight); canvas.drawRect(rectF, mPaint); canvas.restore(); }}

在Activity的onCreate()中调用:

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_forth); //一句话实现绑定 new SlideLayout(this).bind(); }

小结:两种方法归根结底都是把DecorView下的子View移除添加到SlideLayout,再将SlideLayout添加到DecorView这种思路,只是移动的方式不同而已。再说第二种方法使用ViewDragHelper只能从边缘拖拽,这显得不那么友好。

┗|`O′|┛ 如果你有好的想法思路,欢迎共享讨论。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表