使用Snake,安卓也能轻松实现类iOS滑动关闭功能

2018-01-12 11:10:13来源:网络收集作者:咖啡不加糖人点击

分享

阿里云爆款


坦率地讲,我并不是一个果粉。我也不觉得iOS系统比Android优秀,曾经有过一段时间将iPhone用作主流机。最后还是换成了安卓机,原因是iPhone的性价比的确不高,加上系统的一些限制,可玩性非常有限。而如果你问我,iOS系统里面有什么你特别喜欢的功能,滑动关闭无疑是其中一个。当人们在专注屏幕内容的时候,还要转移注意力聚焦屏幕下方的按钮,其实是有一些成本的,最直观的感觉就是不太自然。用过iPhone后再用安卓,人们总是习惯性地右滑...

Demo下载体验

使用Snake,安卓也能轻松实现类iOS滑动关闭功能



为了实现类似iOS的滑动关闭效果,在大约一年多前,我开发了一个小工具Snake。使用这个小工具仅需要一行代码就可以轻松集成滑动关闭功能,当前这个工具的最新版本是0.1.0,老版本截止于0.0.6。



对于老版本的设计,有两个明显的缺陷:


必须在style文件中添加如下样式设置,将Window设置为透明


@android:color/transparent
true


在Fragment中使用必须继承父类me.foji.snake.app.Fragment或me.foji.snake.v4.app.Fragment,并且要转移布局代码到onBindView中



为了克服这些问题,我完全重写了这个小工具,新版本将来到0.1.0。新版本不仅解决了上面两个问题,而且对代码进行了简化,去掉了冗余设计。同时,在灵活性上面有了大幅度的提高,可以让你完全不要改动原有代码架构就能使用滑动关闭功能,真正的零侵入性设计。废话不多说,一起来看一下,怎么使用吧!


如何使用

1)添加依赖


dependencies {
// Gradle高版本这里可以使用implementation代替compile
// x.x.x代表最新版本号,请到文章底部点击Github链接查看
// 截止文章截稿日期,最新版本号都是0.1.0
compile 'com.youngfeng.android:snake:x.x.x'
annotationProcessor 'com.youngfeng.android:snake-compiler:x.x.x'
}

2) 在Application的onCreate方法中,对Snake进行初始化


public class SnakeApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Snake.init(this);
}
}

3)在Activity中使用


在需要使用滑动关闭的Activity类头添加@EnableDragToClose注解


@EnableDragToClose()
public class FirstActivity extends BaseActivity {


在Activity.onCreate方法中,使用host接口对当前Activity进行托管


@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Snake.host(this);
}

以上两个步骤已经使Activity拥有了滑动关闭功能,不相信吗?试试看!



4)在Fragment中使用


同样地,在需要使用滑动关闭的Fragment类头添加@EnableDragToClose注解



如果是android.app.Fragment的子类,使用Snake.newProxy(FragmentA.class)创建当前Fragment实例;如果是android.support.v4.app.Fragment的子类,使用Snake.newProxySupport(FragmentA.class)创建当前Fragment实例。



注意:Fragment类中不需要使用host接口对其进行托管,Snake将自动完成托管。



通过以上四个步骤,你已经成功完成了对滑动关闭的集成。可是,在不同的手机上测试,滑动时你依然会发现几个问题:


Activity中滑动动画正常,使用返回键回退和点击进入的动画却表现不一致



Fragment中除了存在上述一样的问题外,在滑动关闭后,动画还会播放一次,导致整体看起来不和谐
相信你应该知道,解决第一个问题其实很简单,只要在启动Activity和结束Activity的时候使用overridePendingTransition(R.anim.snake_slide_in_right,
R.anim.snake_slide_out_left)设置动画即可,具体的设置可以参照 Github Demo进行处理。



而对于Fragment的设置相对较为麻烦,在启动的时候我们可以通过setCustomAnimation对其启动和回退动画进行统一设置。可是在回退的时候,却不能关闭某一次动画播放,导致了动画重复播放的问题。为了避免这个问题,Snake增加了wrap和SnakeAnimationController两个接口,通过这两个接口联合使用就可以避免这个问题。



具体要怎么做呢?看这里:


public class BaseFragment extends Fragment implements SnakeAnimationController {
private boolean mDisableAnimation;
@Override
public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
return Snake.wrap(super.onCreateAnimator(transit, enter, nextAnim), this);
}
@Override
public void disableAnimation(boolean disable) {
mDisableAnimation = disable;
}
@Override
public boolean animationDisabled() {
return mDisableAnimation;
}
}

PS:重新onCreateAnimation的方式完全一致,Snake的wrap接口也可以适用。



注意:这个操作强烈建议在Fragment基础父类中进行处理,通过这种方式你也可以自己调用disableAnimation接口控制回退动画的播放。



以上几个操作已经完全可以正常使用滑动关闭了。可是,你可能还有一些特殊的需求,下面我通过QA的方式来模拟六种使用场景,如果还有没有涵盖的使用场景,请在评论下方告诉我!


场景一:如果我想对某个特殊的页面禁用滑动关闭,需要怎么做?
答:很简单,注解EnableDragToClose中可以接受一个Boolean参数,用于控制滑动关闭功能的开启或关闭。因此,你只需要这样做就可以了!


@EnableDragToClose(false)
public class FirstActivity extends BaseActivity {


场景二:如果我想对某个页面动态开启或关闭,换句话说,检测到某些特殊情况开启滑动关闭功能,某些情况下禁用滑动关闭功能,注解做不到吧?Snake可以做到吗?
答:Snake已经为你考虑到了这一点,我们提供了接口enableDragToClose(Activity activity, boolean
enable),Fragment参数也有同名接口。因此,你只需要这样做:


if(条件a) {
Snake.enableDragToClose(this, true);
} else if(条件b) {
Snake.enableDragToClose(this, false);
}


场景三:想象这样一种场景,假设页面中有视频正在播放,我想在滑动开始后关闭视频播放,结束播放继续,可以做到吗?
答:当然可以!为了满足你对滑动过程的控制,Snake提供了**addDragListener(Activity activity, Snake.OnDragListener onDragListener) **接口,用于监听整个滑动过程的。具体监听实现,看这里:


public static abstract class OnDragListener {
public void onDragStart(View view) {}
public void onDrag(View view, int left) {}
public void onRelease(View view, float xVelocity) {}
}


场景四:如果在某些特殊场景下,页面滑动事件出现了冲突,是否有办法补救?
答:可以!为了防止在某些特殊场景下,滑动事件出现冲突,Snake提供了接口public static
void setCustomTouchInterceptor(@NonNull Activity activity, SnakeTouchInterceptor interceptor)实现对事件拦截的自定义处理。通常情况下,你不需要理会这个方法,如果确实发现是因为事件冲突问题导致了使用异常,才需要使用这个方法完成辅助处理。



场景五:关于Fragment,我看到你使用了Snake.newProxy进行了实例的创建。可是,如果我有多个构造方法呢?或者说,我没有提供默认构造方法实现,怎么办?这种场景可以处理吗?
答:当然可以!为了满足对多构造器实例创建的处理,Snake提供了一个新的注解@PrimaryConstructor用于指定主构造器,指定后,Snake会以这个构造器创建Fragment实例,但这里要求你传入构造器所需的参数,类似这样:


Fragment fragment = Snake.newProxy(xx.class, objA, objB);


场景五:说了这么多,你似乎忽略了一个主流问题!如果我想对滑动的样式进行设置,怎么办?难道不允许吗?
答:这当然也是允许的,不过不推荐你进行自定义设置,因为默认样式已经完全可以满足需求了。但如果你一定要修改,我也不反对。如果你要对全局进行样式修改,我们提供了snake.xml配置文件对样式进行设置。


<?xml version="1.0" encoding="utf-8"?>



false

false

2000

false

#00000000

#55000000



如果要对单个页面进行滑动样式修改,我们提供了@SetDragParameter注解:


/**
* 仅监听快速滑动关闭
*/
boolean onlyListenToFastSwipe() default false;
/**
* 快速滑动最小检测速度
*/
int minVelocity() default 2000;
/**
* 隐藏阴影边缘
*/
boolean hideShadowOfEdge() default false;
/**
* 阴影起始颜色(阴影边缘隐藏后,该设置失效)
*/
String shadowStartColor() default "#00000000";
/**
* 阴影边缘结束颜色(阴影边缘隐藏后,该设置失效)
*/
String shadowEndColor() default "#50000000";

注意:xml配置文件名必须是snake.xml,配置文件应放置在assets目录下面。



场景六:针对单个页面逐一去开启滑动关闭功能实在太麻烦了,是否可以针对所有页面开启滑动关闭功能呢?
答:当然可以!首先,针对Activity和Fragment你需要有一个统一的基类,使用方式与上文介绍完全一致。如果是Activity,先添加注解@EnableDragToClose,然后在onCreate方法中使用host接口对其进行托管,像这样:


@EnableDragToClose()
public class BaseActivity extends Activity {
@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Snake.host(this);
}
}

如果是Fragment,同样地,先添加注解@EnableDragToClose,然后在跳转到Fragment的时候使用Snake.newProxy或Snake.newProxySupport创建Fragment实例即可。


使用总结

为了让你对整个使用过程有一个更直观的了解,我用一个简单的表格来给你展示具体使用方法:


使用步骤
Activity
android.app.Fragment
android.support.v4.app.Fragment
第一步
添加注解@EnableDragToClose
同Activity
同Activity第二步
托管: Snake.host(this)
使用Snake.newProxy创建实例
使用Snake.newProxySupport创建实例第三步
startActivity和finish中使用overridePendingTransition导入Snake内置动画
实现接口SnakeAnimationController,重写onCreateAnimation或onCreateAnimator方法,使用Snake.wrap包裹父类实现并返回
同android.app.Fragment第四步
----
使用setCustomAnimations导入Snake内置动画
同android.app.Fragment
以上步骤省略了Snake在Application中初始化以及导入依赖的过程,详细步骤可以参考 Github


简单说明

这里容易混淆的一个概念就是:注解@EnableDragToClose和Snake.enableDragToClose接口。其实,这两个部分是有一定的区别的,注解是用于标记当前页面是否需要开启滑动关闭功能,如果需要开启,注解始终需要。但如果你希望当前页面始终关闭【滑动关闭】功能,你可以在注解中传入参数false,而如果你希望动态控制【滑动关闭】功能的开启或关闭,则需要使用Snake.enableDragToClose接口来控制。如果你没有添加注解到类头,直接使用接口开启滑动关闭功能,将会报错。


Snake版本兼容问题

Snake 0.1.0不兼容0.0.6极其以前版本,如果你使用了旧版本实现,推荐暂时不要替换,在新的APP中强烈推荐使用0.1.0极其以上版本。


Android系统版本兼容问题

由于Android系统的一些限制,在低于21版本Activity滑动联动的实现上有一些问题。为了避免这个问题,我在低版本的使用上禁用了拖拽,仅使用快速滑动关闭当前页面。这里我推荐使用全Fragment或Activity
+ 多Fragment设计。



在使用过程中,如果你有任何疑问,请点击下方链接参考Github官方文档:
https://github.com/yuanhoujun/AndroidSlideTo_Close


新版本规划


增加更多控制接口



提供WebView和X5WebView滑动关闭的支持

特别鸣谢

感谢 言小诺01 同学提供图标设计。



PS:走过路过,不要错过,点个赞,不要钱哦 -_-




想要学习更多开发知识,请扫描下方二维码关注【欧阳锋工作室】



使用Snake,安卓也能轻松实现类iOS滑动关闭功能




想要获得更好阅读体验,请 阅读原文



最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台