滑动返回-方式2
来源:互联网 发布:魔兽7.0装备数据库 编辑:程序博客网 时间:2024/05/08 10:49
滑动返回-方式2
SwipeBackLayout
项目地址:Alex-Cin/SwipeBackLayout
之前写过一个 在Activity 里面,利用dispatchTouchEvent方法,实现了滑动返回,今天写一个自定义控件,并借助ViewDragHelper实现的滑动返回
- 先看效果图
核心代码量不多,注释很详细了
package github.alex.swipebacklayout;/** * 作者:alex * 时间:2016/8/12 11:49 * */public class SwipeBackLayout extends FrameLayout { private ViewDragHelper viewDragHelper; private View rootView; private Activity activity; /** * 手机屏幕的 宽度 */ private int screenWidth; /** * 是否 允许 执行 滑动返回操作 */ private boolean canSwipeBack; private OnSwipeBackListener onSwipeBackListener; public SwipeBackLayout(Context context) { super(context); initView(); } public SwipeBackLayout(Context context, AttributeSet attrs) { super(context, attrs); initView(); } private void initView() { screenWidth = getScreenWidth(); canSwipeBack = true; ViewDragHelperCallback dragHelperCallback = new ViewDragHelperCallback(); viewDragHelper = ViewDragHelper.create(this, 1.0F, dragHelperCallback); /*跟踪左边界拖动*/ viewDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT); } /** * 绑定 Activity * * @param activity 容器 Activity */ public SwipeBackLayout attachActivity(Activity activity) { this.activity = activity; ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView(); View content = decor.getChildAt(0); decor.removeView(content); rootView = content; addView(content); decor.addView(this); return this; } /** * 是否 允许 执行 滑动返回操作 */ public SwipeBackLayout canSwipeBack(boolean canSwipeBack) { this.canSwipeBack = canSwipeBack; return this; } public SwipeBackLayout onSwipeBackListener(OnSwipeBackListener onSwipeBackListener) { this.onSwipeBackListener = onSwipeBackListener; return this; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (!canSwipeBack) { return false; } /*拦截代理*/ return viewDragHelper.shouldInterceptTouchEvent(ev); } /** * 这里必须 返回 true,否则 viewDragHelper 将会失效 */ @Override public boolean onTouchEvent(MotionEvent event) { if (!canSwipeBack) { return false; } LogUtil.e("进来了"); /*Touch Event 代理*/ viewDragHelper.processTouchEvent(event); //return super.onTouchEvent(event); return true; } /*view 刚初始化的时候就会被调用一次*/ @Override public void computeScroll() { super.computeScroll(); if (!isInEditMode() && (viewDragHelper != null) && viewDragHelper.continueSettling(true)) { /*开启自动滑动*/ ViewCompat.postInvalidateOnAnimation(this); invalidate(); } } private final class ViewDragHelperCallback extends ViewDragHelper.Callback { /** * 手指释放的时候回调 */ public void onViewReleased(View releasedChild, float xvel, float yvel) { LogUtil.e("进来了"); // 拖动距离大于屏幕的一半右移,拖动距离小于屏幕的一半左移 int left = releasedChild.getLeft(); if (left > getWidth() / 2) { viewDragHelper.settleCapturedViewAt(getWidth(), 0); invalidate(); } else { viewDragHelper.settleCapturedViewAt(0, 0); invalidate(); } } /** * 当captureview的位置发生改变时回调 */ @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { super.onViewPositionChanged(changedView, left, top, dx, dy); LogUtil.e(" 进度 = " + left * 100 / screenWidth); if (onSwipeBackListener != null) { onSwipeBackListener.onSwipeProgress(left * 100 / screenWidth); } if (left >= (screenWidth - 4)) { finish(); } } /** * 当触摸到边界时回调。 */ public void onEdgeTouched(int edgeFlags, int pointerId) { super.onEdgeTouched(edgeFlags, pointerId); /**捕捉要拖拽的对象*/ viewDragHelper.captureChildView(rootView, pointerId); } /** * true的时候会锁住当前的边界,false则unLock。 */ public boolean onEdgeLock(int edgeFlags) { return false; } /** * 在边界拖动时回调 * 返回值为true 可以滑动 ;为false 则不能滑动 */ public void onEdgeDragStarted(int edgeFlags, int pointerId) { /*移动子 View*/ viewDragHelper.captureChildView(rootView, pointerId); } public int getViewHorizontalDragRange(View child) { return getMeasuredWidth() - child.getMeasuredWidth(); } /** * 尝试捕获子view, 返回true表示允许。 * * @param child 尝试捕获的view * @param pointerId 指示器id? */ public boolean tryCaptureView(View child, int pointerId) { return false; } /** * 处理水平方向上的拖动,返回值就是最终确定的移动的位置。 * 实际上就是判断如果这个坐标在layout之内 那我们就返回这个坐标值。 * 除此之外就是如果你的layout设置了padding的话, * 也可以让子view的活动范围在padding之内的. * * @param child 被拖动到view * @param left 移动到达的x轴的距离 * @param dx 建议的移动的x距离 */ public int clampViewPositionHorizontal(View child, int left, int dx) { LogUtil.e("进来了"); /*拖动限制(大于左边界)*/ return Math.max(0, left); } } private void finish() { if (onSwipeBackListener != null) { onSwipeBackListener.onSwipeProgress(100); onSwipeBackListener.onFinish(); } if (activity != null) { activity.finish(); } if (viewDragHelper != null) { viewDragHelper.cancel(); } if (rootView != null) { rootView.destroyDrawingCache(); } viewDragHelper = null; rootView = null; activity = null; } /** * 获得屏幕高度 */ private int getScreenWidth() { WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.widthPixels; }}
最后奉上 源码 和 apk
0 0
- 滑动返回-方式2
- 滑动返回
- 仿手机QQ聊天列表滑动菜单删除和手势滑动返回的两种方式
- ios 滑动返回 系统滑动返回
- 2种方式实时滑动的ViewPager
- iOS7滑动返回
- iOS7滑动返回
- NavigationControllerr滑动返回
- iOS7滑动返回
- iOS7滑动返回
- 右滑动返回
- iOS7滑动返回
- iOS7滑动返回
- Android滑动返回 SwipeBack
- iOS7滑动返回
- iOS7滑动返回
- iOS7滑动返回
- NavigationControllerr滑动返回
- 第八周—求值
- EXSI+VSPHERE的安装配置+三种虚拟磁盘模式
- mvc 权限控制
- 网页编码
- 父类对象 到底能不能强转换为 子类对象
- 滑动返回-方式2
- [kuangbin带你飞]专题六 最小生成树 F POJ 1789
- 自动化运维管理fabric
- 解决AndroidStudio未导入Apache.http等包的问题
- Mac开机显示器没有反应解决方法
- 阶乘求和
- python 字符串方法isdigit()
- Struts2类型转换,数据验证
- 【协议】深度了解HTTP/2