资讯专栏INFORMATION COLUMN

Android实现SwipeBack(右滑退出)效果

sixgo / 2799人阅读

摘要:效果演示初始状态滑动中状态结束状态这是目前实现在中的效果。在中采用的方案是使用一个叫的未公开的,再配合中把设置为,即可实现上层的背景为透明。使用这个回调进行一些是否可以滑动以及滑动距离的判定。实现这个效果就是这么简单欢迎关注我以及

效果演示 初始状态

滑动中状态

结束状态

这是目前实现在SegmentFault for Android v2.6中的效果。
一切一切的之前,感谢 ikew0ng/SwipeBackLayout
我使用这个库,并经过一些修改,支持了Android 4.0以上所有的版本。
我们来分析下SwipeBackLayout的源码

一些修改

我之前做过实验,碰到的最大问题是上层的Activity底下并不是透明的,因此看不见下层Activity的视图。
SwipeBackLayout中采用的方案是使用一个叫convertToTranslucent的未公开的api,再配合theme
windowIsTranslucent设置为true,即可实现上层的Window背景为透明。

这里要注意的地方是调用convertToTranslucent可以使用反射的方法进行调用,但是在Lollipop中,它的参数变成了两个,而在5.0以下是一个参数,所以需要在源码中对Util.convertActivityToTranslucent这个方法进行一些修改。

javapublic static void convertActivityToTranslucent(Activity activity) {
    try {
        Class[] t = Activity.class.getDeclaredClasses();
        Class translucentConversionListenerClazz = null;
        Class[] method = t;
        int len$ = t.length;

        for(int i$ = 0; i$ < len$; ++i$) {
            Class clazz = method[i$];
            if(clazz.getSimpleName().contains("TranslucentConversionListener")) {
                translucentConversionListenerClazz = clazz;
                break;
            }
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Method var8 = Activity.class.getDeclaredMethod("convertToTranslucent", translucentConversionListenerClazz, ActivityOptions.class);
            var8.setAccessible(true);
            var8.invoke(activity, new Object[]{null, null});
        } else {
            Method var8 = Activity.class.getDeclaredMethod("convertToTranslucent", translucentConversionListenerClazz);
            var8.setAccessible(true);
            var8.invoke(activity, new Object[]{null});
        }
    } catch (Throwable e) {
    }

}

使得能适配4.0 - 5.0+所有的设备

源码分析

我们可以看它的源码可以知道,它是利用ViewDragHelper对View进行拖移效果的,ViewDragHelper主要帮助我们完成了对速度、加速度以及释放后的一些逻辑的设置,大大简化了我们对触摸事件的处理。
我们看下SwipeBackLayout是如何嵌入到我们要的Activity里去的

 public void attachToActivity(Activity activity) {
    this.mActivity = activity;
    // .... 省略部分代码
    ViewGroup decor = (ViewGroup)activity.getWindow().getDecorView();
    ViewGroup decorChild = (ViewGroup)decor.getChildAt(0);
    decorChild.setBackgroundResource(background);
    decor.removeView(decorChild);
    this.addView(decorChild);
    this.setContentView(decorChild);
    decor.addView(this);
}

我们可以看到,本来Activity调用setContentView之后,会把我们要的layout加到windowdecorView上,我们在这里把window中的decorView的子元素改成SwipeBackLayout,然后把原先的contentView加到decorView下,使得ViewDragHelper附着在SwipeBackLayout上。

this.mDragHelper = ViewDragHelper.create(this, new SwipeBackLayout.ViewDragCallback());

ViewDragHelper使用ViewDragHelper.Callback这个回调进行一些View是否可以滑动以及滑动距离的判定。
我们来看下ViewDragHelper.Callback接口的声明
官方文档传送门:http://developer.android.com/reference/android/support/v4/widget/ViewD...

定义 注释
int clampViewPositionHorizontal (View child, int left, int dx) 此方法返回一个值,告诉Helper,这个view能滑动的最大(或者负向最大)的横向坐标
int clampViewPositionVertical (View child, int top, int dy) 此方法返回一个值,告诉Helper,这个view能滑动的最大(或者负向最大)的纵向坐标
int getOrderedChildIndex (int index) 返回这个索引所指向的子视图的Z轴坐标
int getViewHorizontalDragRange (View child) 返回指定View在横向上能滑动的最大距离
int getViewVerticalDragRange (View child) 返回指定View在纵向上能滑动的最大距离
void onEdgeDragStarted (int edgeFlags, int pointerId) 当边缘开始拖动的时候,会调用这个回调
boolean onEdgeLock (int edgeFlags) 返回指定的边是否被锁定
void onEdgeTouched (int edgeFlags, int pointerId) 当边缘被触摸时,系统会回调这个函数
void onViewCaptured (View capturedChild, int activePointerId) 当有一个子视图被指定为可拖动时,系统会回调这个函数
void onViewDragStateChanged (int state) 拖动状态改变时,会回调这个函数
void onViewPositionChanged (View changedView, int left, int top, int dx, int dy) 当子视图位置变化时,会回调这个函数
void onViewReleased (View releasedChild, float xvel, float yvel) 当手指从子视图松开时,会调用这个函数,同时返回在x轴和y轴上当前的速度
boolean tryCaptureView (View child, int pointerId) 系统会依次列出这个父容器的子视图,你需要指定当前传入的这个视图是否可拖动,如果可拖动则返回true 否则为false

利用ViewDragHelper的回调函数,我们知道了视图被拖动的距离,然后根据这个距离和宽度的一些比例,我们可以对SwipeBackLayout的父容器进行一些透明度和阴影的设置。

实现这个效果就是这么简单~

  

欢迎关注我Github 以及 @Gemini

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/12294.html

相关文章

  • android一个右滑退出效果实现

    摘要:首先,网上介绍相关右滑退出实现的文章相当多,本文只是我自己实现的一个记录。考虑到子可能是等自身有横向滑动属性的控件,可以对这些控件单独处理,或者开一个手动添加忽略右滑退出子的接口。 首先,网上介绍相关右滑退出实现的文章相当多,本文只是我自己实现的一个记录。 思路与分析 介绍: android上最出名的右滑退出库莫过于SwipeBackLayout,效果如下:showImg(https:...

    iOS122 评论0 收藏0
  • 使用SlidingPaneLayout 实现仿微信的滑动返回

    摘要:上周公司的项目改版要求加上一个右滑返回上一个界面于是就在网上找了一些开源库打算实现但是在使用的时候遇见了许多的问题试了两天用过等库都没成功然后在看见了使用来实现的一个滑动返回案例然后就看了看发现不错于是就使用了这个虽然上面链接里面已近写好啦上周,公司的项目改版要求加上一个右滑返回上一个界面,于是就在网上找了一些开源库打算实现.但是在使用的时候遇见了许多的问题.试了两天用过https://gi...

    番茄西红柿 评论0 收藏0
  • 不可错过的android好文 - 收藏集 - 掘金

    摘要:针对此种情况,下文把做开发以来遇到的经典问题整理出来,希望对有需要的朋友开发工程师面试指南掘金开发工程师面试指南,作者是陶程,由梁观全贡献部分。 Android 常见问题集锦 - Android - 掘金前言:在开发中,每个人或多或少会遇到各种各样的问题,有些问题依据代码思路调试就可以定位出来,而大部分的问题都是经验性问题,遇到过就很容易解决,但在第一次遇到时往往会花费大量时间来定位问...

    derek_334892 评论0 收藏0
  • Bamboy右滑关闭2.0,无需透明主题的右滑关闭(附源码)

    摘要:右滑关闭简介很多中都会有右滑关闭功能,尤其是在全面屏时代更显得尤为重要,但是,禁止非全屏的使用透明主题,否则会引发这导致了体验最优的右滑关闭方案则不能再使用,除非有微信那种黑科技。 SlidingShut 右滑关闭 简介 很多APP中都会有右滑关闭功能, 尤其是在全面屏时代更显得尤为重要, 但是, Android 8.0禁止非全屏的Activity使用透明主题, 否则会引发:...

    马龙驹 评论0 收藏0
  • Bamboy右滑关闭2.0,无需透明主题的右滑关闭(附源码)

    摘要:右滑关闭简介很多中都会有右滑关闭功能,尤其是在全面屏时代更显得尤为重要,但是,禁止非全屏的使用透明主题,否则会引发这导致了体验最优的右滑关闭方案则不能再使用,除非有微信那种黑科技。 SlidingShut 右滑关闭 简介 很多APP中都会有右滑关闭功能, 尤其是在全面屏时代更显得尤为重要, 但是, Android 8.0禁止非全屏的Activity使用透明主题, 否则会引发:...

    _Dreams 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<