实现Activity滑动退出
来源:互联网 发布:js 数字转化成幂次方 编辑:程序博客网 时间:2024/06/08 06:32
原文链接: http://www.jianshu.com/p/7b0dfd2bf011#
实现Activity滑动退出
很多应用在二级详情页面加入了滑动退出activity的效果,很方便,心血来潮,想着自己也来实现这个效果,就当做练手吧。
实现View的滑动有很多种方法,如自己在onTouchEvent中处理触摸事件,然后滚动View到相应位置,也可以用google V4包为我们提供的ViewDragHelper来处理触摸事件,我们这里选择后者,因为滑动退出操作都是在屏幕的边缘时触发,而ViewDragHelper刚好提供了想要的实现,可以说利用ViewDragHelper来实现我们的需求非常简单。
先定义一个ViewGroup,并做一些必要的变量声明
BaseSwipeLayout
public class BaseSwipeLayout extends FrameLayout{ private View mDragView; private ViewDragHelper mViewDragHelper; private Point mAutoBackOrignalPoint = new Point(); private Point mCurArrivePoint = new Point(); private int mCurEdgeFlag = ViewDragHelper.EDGE_LEFT; private int mSwipeEdge = ViewDragHelper.EDGE_LEFT; public BaseSwipeLayout(Context context) { this(context, null); } public BaseSwipeLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public BaseSwipeLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } }
既然使用ViewDragHelper,我们把触摸事件交给ViewDragHelper处理,ViewDragHelper不熟悉的同学,相关知识,网上一大堆,自行查看
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { return mViewDragHelper.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { mViewDragHelper.processTouchEvent(event); return true; }
下面对ViewDragHelper的配置,比较简单,大家看代码吧。
private void init() { mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() { @Override public boolean tryCaptureView(View child, int pointerId) { return false; } @Override public int clampViewPositionHorizontal(View child, int left, int dx) { mCurArrivePoint.x = left; //允许左右触发滑动,否则return 0 if (mCurEdgeFlag != ViewDragHelper.EDGE_BOTTOM) { return left; }else return 0; } @Override public int clampViewPositionVertical(View child, int top, int dy) { mCurArrivePoint.y = top; //允许底部触发滑动,否则return 0 if (mCurEdgeFlag == ViewDragHelper.EDGE_BOTTOM) { return top; }else return 0; } @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { super.onViewReleased(releasedChild, xvel, yvel); switch (mCurEdgeFlag) { case ViewDragHelper.EDGE_LEFT: //水平滑动超过一半,触发结束 if (mCurArrivePoint.x > getWidth()/2) { mViewDragHelper.settleCapturedViewAt(getWidth(), mAutoBackOrignalPoint.y); }else { mViewDragHelper.settleCapturedViewAt(mAutoBackOrignalPoint.x, mAutoBackOrignalPoint.y); } break; case ViewDragHelper.EDGE_RIGHT: //水平滑动超过一半,触发结束 if (mCurArrivePoint.x < -getWidth()/2) { mViewDragHelper.settleCapturedViewAt(-getWidth(), mAutoBackOrignalPoint.y); }else { mViewDragHelper.settleCapturedViewAt(mAutoBackOrignalPoint.x, mAutoBackOrignalPoint.y); } break; case ViewDragHelper.EDGE_BOTTOM: //垂直滑动超过一半,触发结束 if (mCurArrivePoint.y < -getHeight()/2) { mViewDragHelper.settleCapturedViewAt(mAutoBackOrignalPoint.x, -getHeight()); }else { mViewDragHelper.settleCapturedViewAt(mAutoBackOrignalPoint.x, mAutoBackOrignalPoint.y); } break; } mCurArrivePoint.x = 0; mCurArrivePoint.y = 0; invalidate(); } @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { super.onViewPositionChanged(changedView, left, top, dx, dy); switch (mCurEdgeFlag) { case ViewDragHelper.EDGE_LEFT: if (left >= getWidth()) { if (mFinishScroll != null) { mFinishScroll.complete(); } } break; case ViewDragHelper.EDGE_RIGHT: if (left <= -getWidth()) { if (mFinishScroll != null) { mFinishScroll.complete(); } } break; case ViewDragHelper.EDGE_BOTTOM: if (top <= -getHeight()) { if (mFinishScroll != null) { mFinishScroll.complete(); } } break; } } @Override public void onEdgeDragStarted(int edgeFlags, int pointerId) { mCurEdgeFlag = edgeFlags; if (mDragView == null) mDragView = getChildAt(0); mViewDragHelper.captureChildView(mDragView, pointerId); } }); mViewDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT); }
这里还有个步骤不要忘了,手指离开屏幕或者滑动超过屏幕的时候,我们触发了ViewGroup自行完全滚动出屏幕的调用,所以我们需要在computeScroll中做检查,如果滚动没有结束,刷新View,继续滚动。
@Override public void computeScroll() { if (mViewDragHelper.continueSettling(true)) { invalidate(); } }
这样我们自定义的BaseSwipeLayout打造完毕,我们把它设为activity的根布局测试一下
<?xml version="1.0" encoding="utf-8"?><com.aliouswang.swipeback.widget.BaseSwipeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:id="@+id/swipe_layout" android:layout_height="match_parent"> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:text="Swipe Back Demo" android:gravity="center" android:textColor="@android:color/white" android:background="@android:color/holo_red_light" android:layout_width="match_parent" android:layout_height="100dp" /> <TextView android:text="Swipe Back Demo" android:gravity="center" android:textColor="@android:color/white" android:background="@android:color/holo_blue_light" android:layout_width="match_parent" android:layout_height="100dp" /> <TextView android:text="Swipe Back Demo" android:gravity="center" android:textColor="@android:color/white" android:background="@android:color/holo_green_light" android:layout_width="match_parent" android:layout_height="100dp" /> <TextView android:text="Swipe Back Demo" android:gravity="center" android:textColor="@android:color/white" android:background="@android:color/holo_purple" android:layout_width="match_parent" android:layout_height="100dp" /> <TextView android:text="Swipe Back Demo" android:gravity="center" android:textColor="@android:color/white" android:background="@android:color/holo_green_dark" android:layout_width="match_parent" android:layout_height="100dp" /> <TextView android:text="Swipe Back Demo" android:gravity="center" android:textColor="@android:color/white" android:background="@android:color/holo_red_dark" android:layout_width="match_parent" android:layout_height="100dp" /> <TextView android:text="Swipe Back Demo" android:gravity="center" android:textColor="@android:color/white" android:background="@android:color/holo_blue_dark" android:layout_width="match_parent" android:layout_height="100dp" /> <TextView android:text="Swipe Back Demo" android:gravity="center" android:textColor="@android:color/white" android:background="@android:color/holo_orange_dark" android:layout_width="match_parent" android:layout_height="100dp" /> </LinearLayout> </ScrollView></com.aliouswang.swipeback.widget.BaseSwipeLayout>
当然,我们已经实现了整个功能,但是有一点很不爽的是,我们必须将BaseSwipeLayout作为布局的根,这样实现还不够优雅,我们能不能不改变我们原有的布局文件,却依然能加入滑动退出功能。
这里我们要介绍一个DecorView,它是Window的最顶层View,它含有一个子LinearLayout,代表整个Window,包括通知栏,状态栏,内容显示区域,所以我们activity页面是DecorView的子View的子View,那么我们能不能直接给DecorView的子View添加到我们的BaseSwipeLayout,再将BaseSwipeLayout添加到DecorView,当然是可以的,而且这种方式,我们不需要改变原来的布局文件,更加优雅。
我们定义一个SwipeHelper类,辅助我们进行BaseSwipeLayout插入操作。
public class SwipeHelper { private Activity mActivity; private BaseSwipeLayout mBaseSwipeLayout; public SwipeHelper(Activity activity) { this.mActivity = activity; } public void onActivityCreate() { mBaseSwipeLayout = (BaseSwipeLayout) LayoutInflater.from(mActivity) .inflate(R.layout.swipe_layout, null); mBaseSwipeLayout.setOnFinishScroll(new BaseSwipeLayout.OnFinishScroll() { @Override public void complete() { mActivity.finish(); } }); } public void onPostCreate() { mBaseSwipeLayout.attachToActivity(mActivity); } public void setSwipeEdge(int edgeFlag) { mBaseSwipeLayout.setSwipeEdge(edgeFlag); }}
BaseSwipeLayout
//核心代码,绑定到相应activity public void attachToActivity(Activity activity) { this.mActivity = activity; TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{ android.R.attr.windowBackground }); int background = a.getResourceId(0, 0); a.recycle(); ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); ViewGroup decorChild = (ViewGroup) decorView.getChildAt(0); decorChild.setBackgroundResource(background); decorView.removeView(decorChild); addView(decorChild); decorView.addView(this); }
需要添加滑动退出的activity,添加想要代码
private SwipeHelper mSwipeHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.view_drag_helper_act_layout); mSwipeHelper = new SwipeHelper(this); mSwipeHelper.onActivityCreate(); mSwipeHelper.setSwipeEdge(ViewDragHelper.EDGE_RIGHT); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mSwipeHelper.onPostCreate(); }
到此我们的代码基本完成,源码我放到了BaseSwipe,欢迎指教!
参考:https://github.com/ikew0ng/SwipeBackLayout
----------------------------------------------------------------------------------------------------------------------------
下面为我遇见的问题及我的解决方案:问题:滑动退出时的背景是白色的,而不是下层的页面.
答: 首先看你的activity是继承于Activity还是AppCompatActivity.
1.是Activity,在清单文件中你这个Activity标签里写下:android:theme="@android:style/Theme.Translucent.NoTitleBar".
2.是AppCompatActivity,用自定义透明背景.在style.xml里定义
<style name="NoTitleTranslucentTheme" parent="AppTheme"><item name="android:windowNoTitle">true</item><!-- 看你要不要title决定加不加这行 --><item name="android:windowBackground">@android:color/transparent</item><item name="android:windowIsTranslucent">true</item></style>
然后同上,在清单文件声明这个activity的标签里引用就好了.
<activity android:name=".ui.activity.xxxActivity" android:theme="@style/NoTitleTranslucentTheme"/>
- 实现Activity滑动退出
- 简单实现Activity退出时向下滑动退出的效果
- activity支持滑动退出
- 仿微信滑动退出Activity
- 仿微信滑动退出Activity
- 滑动退出Activity
- Activity滑动退出
- Android UI效果实现——Activity滑动退出效果
- Android实现IOS向右滑动退出当前Activity
- activity向右滑动关闭退出
- 滑动退出Activity的两种方法
- activity实现滑动效果
- 实现退出Activity的方式
- 实现activity管理器一次退出所有activity
- 实现activity管理器一次退出所有activity
- 实现左右滑动切换Activity
- android 实现滑动切换activity
- SlidingPaneLayout实现Activity滑动返回
- java找出字符串里面的邮箱和电话号码
- 人脸识别几个解决方案分析与测评
- AES加密问题
- matlab函数大全
- Cenos安装nodejs和nodejs依赖管理软件npm
- 实现Activity滑动退出
- 回首大学三年
- C++类的导入导出
- MAC terminal ssh保持连接
- Eclipse Ctrl+左键查看源代码Source not found
- 查找---最大公共子串、最长公共子序列
- 设置edittext不默认选中
- Linux vim编辑器常见命令的使用
- 软件测试基础知识(二)