IMG_0026.JPGSwipeBackLayout是一个在Android平台上实现了Activity滑动返回的库.

实现了左,右,上,下四种手势返回的功能,在ios里滑动返回是系统自带可以配置的功能,而在我们Android上并没有系统级别的提供。

主流应用比如微信,今日头条,就带有滑动返回功能,而且滑动返回是一个非常容易培养用户使用习惯的操作,用惯了滑动返回再用没有滑动返回的应用简直不能好好用了。

SwipeBackLayout应该算是使用范围最广的滑动返回的库了 okay我们就来分析一下这个库是如何实现的:

build.gradle 文件添加类库

compile 'me.imid.swipebacklayout.lib:library:1.0.0'

设置需要滑动返回Activity的Theme style.xml里添加:

true

将Activity继承SwipeBackActivity然后将我们的Activity继承SwipeBackActivity就集成完毕,我们的Activity就默认带有左划返回的功能了,

ThreeActivity extends SwipeBackActivity

//是否允许滑动返回

setSwipeBackEnable(false);

//滑动并关闭activity

scrollToFinishActivity();

//获得SwipeBackLayout对象

getSwipeBackLayout();

当然我们super.onCreate(savedInstanceState);执行之后,调用下面的方法做一些自定义设置:

mSwipeBackLayout.setEdgeTrackingEnabled(SwipeBackLayout.EDGE_RIGHT);//设定从哪个方向可以滑动

mSwipeBackLayout.setEdgeSize(200);//来设置滑动触发的范围等等

mSwipeBackLayout.setScrimColor(R.color.colorAccent);//来设置滑动返回的背景色

MainActivity 全码 如果你单单的只是像我一样学习用法 那看到这 基本就可以ok了 下面的 都是一些源码的分析 那些我也只是作为了解

public class MainActivity extends SwipeBackActivity {

private SwipeBackLayout mSwipeBackLayout;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mSwipeBackLayout=getSwipeBackLayout();

mSwipeBackLayout.setEdgeTrackingEnabled(SwipeBackLayout.EDGE_RIGHT);//设定从哪个方向可以滑动

mSwipeBackLayout.setEdgeSize(200);//来设置滑动触发的范围等等

Button button=(Button)findViewById(R.id.button);

button.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

startActivity(new Intent(MainActivity.this,FirstActivity.class));

}

});

mSwipeBackLayout.addSwipeListener(new SwipeBackLayout.SwipeListener() {

@Override

public void onScrollStateChange(int state, float scrollPercent) {

}

@Override

public void onEdgeTouch(int edgeFlag) {

vibrate(20);

}

@Override

public void onScrollOverThreshold() {

vibrate(20);

}

});

}

/**

* //手机的振动器,是通过this.getSystemService(Service.VIBRATOR_SERVICE)获取的,然后通过用vibrate来

* 实现震动,

* @param duration

*/

private void vibrate(long duration) {

Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);

long[] pattern = {

0, duration

};

vibrator.vibrate(pattern, -1);

}

}

类关系图

SwipeBackLayout的类关系图非常的清晰简单,SwipeBackActivity继承自Activity并且实现了SwipeBackActivityBase接口,SwipeBackActivity,SwipeBackActivityHelper和SwipeBackLayout相互引用,类图上来看还是比较简单的,下面我们来看具体实现:

源码分析

一句话概括SwipeBackLayout的实现原理就是:通过在DecorView和其包含的子View之间添加一个ViewGroup也就是SwipeBackLayout,通过在SwipeBackLayout里处理触摸事件与位移来实现滑动返回的效果。

SwipeBackActivityBase的实现

我们以前说过阅读一个框架的时候,先从它定义的一些接口开始,如果是小项目其实也没有太多的规定,因为代码量本身就不多,所以也可以整体来看,不过我们还是先来看看SwipeBackActivityBase

接口是怎么定义的:

public interface SwipeBackActivityBase {

//得到SwipeBackLayout对象

public abstract SwipeBackLayout getSwipeBackLayout();

//设置是否可以滑动返回

public abstract void setSwipeBackEnable(boolean enable);

//自动滑动返回并关闭Activity

public abstract void scrollToFinishActivity();

}

SwipeBackActivityBase的实现

我们以前说过阅读一个框架的时候,先从它定义的一些接口开始,如果是小项目其实也没有太多的规定,因为代码量本身就不多,所以也可以整体来看,不过我们还是先来看看SwipeBackActivityBase接口是怎么定义的:

public class SwipeBackActivity extends AppCompatActivity implements SwipeBackActivityBase {

private SwipeBackActivityHelper mHelper;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//初始化mHelper

mHelper = new SwipeBackActivityHelper(this);

mHelper.onActivityCreate();

}

@Override

protected void onPostCreate(Bundle savedInstanceState) {

super.onPostCreate(savedInstanceState);

mHelper.onPostCreate();

}

@Override

public SwipeBackLayout getSwipeBackLayout() {

return mHelper.getSwipeBackLayout();

}

@Override

public void setSwipeBackEnable(boolean enable) {

getSwipeBackLayout().setEnableGesture(enable);

}

@Override

public void scrollToFinishActivity() {

Utils.convertActivityToTranslucent(this);

getSwipeBackLayout().scrollToFinishActivity();

}

}

可以看到在onCreate()里创建了一个SwipeBackActivityHelper对象,而在getSwipeBackLayout()方法里通过mHelper得到了对应的SwipeBackLayout对象,所以mHelper应该是负责创建SwipeBackLayout并将SwipeBackLayout添加到Activity里的。

在mHelper的onActivityCreate()方法里创建了SwipeBackLayout对象,并在onPostCreate()方法里将SwipeBackLayout添加到Activity里,逻辑很简单,这里就不贴代码了,最终是调用了SwipeBackLayout的attachToActivity()方法:

public void attachToActivity(Activity activity) {

//获得activity对象

mActivity = activity;

TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{

android.R.attr.windowBackground

});

//得到窗口背景

int background = a.getResourceId(0, 0);

a.recycle();

//得到DecorView对象,并先将decorChild移除并添加到

//SwipeBackLayout里,再添加进DecorView

ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView();

ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);

decorChild.setBackgroundResource(background);

decor.removeView(decorChild);

addView(decorChild);

setContentView(decorChild);

decor.addView(this);

}

这就是整个添加过程,至此我们的Activity里就包含了SwipeBackLayout了,下面我们就来看看SwipeBackLayout的具体实现。

SwipeBackLayout的实现

public SwipeBackLayout(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs);

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

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SwipeBackLayout, defStyle,

R.style.SwipeBackLayout);

int edgeSize = a.getDimensionPixelSize(R.styleable.SwipeBackLayout_edge_size, -1);

...

a.recycle();

final float density = getResources().getDisplayMetrics().density;

final float minVel = MIN_FLING_VELOCITY * density;

mDragHelper.setMinVelocity(minVel);

mDragHelper.setMaxVelocity(minVel * 2f);

}

@Override

public boolean onInterceptTouchEvent(MotionEvent event) {

if (!mEnable) {

return false;

}

try {

return mDragHelper.shouldInterceptTouchEvent(event);

} catch (ArrayIndexOutOfBoundsException e) {

// FIXME: handle exception

// issues #9

return false;

}

}

@Override

public boolean onTouchEvent(MotionEvent event) {

if (!mEnable) {

return false;

}

mDragHelper.processTouchEvent(event);

return true;

}

可以看到是完全委托ViewDragHelper来处理,我们可以看到SwipeBackLayout中的ViewDragHelper并不是直接引用的support包中的ViewDragHelper而是将代码拷贝出来,是因为需要添加一些support中ViewDragHelper并不存在的方法,例如mDragHelper.setEdgeSize(size);,mDragHelper.setMaxVelocity(minVel * 2f);

@Override

protected boolean drawChild(Canvas canvas, View child, long drawingTime) {

Log.d(TAG, "drawChild");

final boolean drawContent = child == mContentView;

boolean ret = super.drawChild(canvas, child, drawingTime);

if (mScrimOpacity > 0 && drawContent

&& mDragHelper.getViewDragState() != ViewDragHelper.STATE_IDLE) {

//绘制边缘垂直阴影

drawShadow(canvas, child);

//绘制背景遮罩

drawScrim(canvas, child);

}

return ret;

}

可以看到阴影和遮罩就是在这个方法里绘制的了

存在的问题

1.部分Android版本不兼容:

在实际使用的时候发现当一个Activity栈内的所有Activity的Theme里都添加了true参数时,在某些Android 4.4.x的手机上或者4.4.x的MIUI上,滑动返回的时候不会看到前面一个Activity而会把桌面显示出来,这应该是这些系统的bug.所以为了避免这些问题,我们需要在最底层的Activity的Theme里设置false来避免这个问题,通常都是我们的MainActivity而且一般这个Activity我们并不需要左划返回的功能,所以这个问题也算是找到了解决办法。

2.性能问题:

由于被设置了true的Activity无法进入onStop()生命周期,所以导致Activity的Window无法回收,所以在多个Activity叠加时会出现明显的卡顿现象,目前并没有特别好的解决办法。

android仿苹果滑动,Android 仿Ios 滑动返回上一目录相关推荐

  1. android 仿支付宝菜单_这个 Android 几乎放弃的设计,iOS 要用上了?

    iOS 和 Android,两个移动时代的操作系统在历经十多年发展后,成熟度之高已经很难再找出大的短板. 如今,这两个系统相似的部分,大概比它们不相似的地方还要多得多.从早期的下拉通知栏,再到现在的侧 ...

  2. android 高仿苹果listview,android listview仿iphone特效

    ios常见视图在顶部往下拉(下冲)或底部往上拉(上冲)有一个弹性回退的动画效果.著名的CM ROM和一些手机厂商也争相集成这种效果.android 从2.3开始实现了下冲到底部和上冲到顶部时颜色渐变动 ...

  3. android用户苹果手表,Android分析苹果手表成功原因

    Apple Watch 并不是市面上首款智能手表,但是自从苹果进入这一领域之后,Apple Watch 就一直霸占着龙头老大的位置.根据最近一次市场统计报告,Apple Watch 在智能手表领域的市 ...

  4. iPhone 计算机 桌面,仿苹果电脑桌面软件 仿苹果桌面软件

    有什么好用的windows10仿苹果的桌面导航软件 windows还是无法象真正的苹果系统那样漂亮的,如果你装了mac的虚拟机,就知道苹果系统是如何的好了. 怎么说呢,你装了后发现,那才叫享受,接着, ...

  5. 解决ios端返回上一个页面不刷新页面的问题

    javascript返回上一个页面也许你会立马想到几种方案: 1.<a href="javascript:history.go(-1)">返回上一页</a> ...

  6. H5页面与ios交互返回上一级

    H5页面与ios交互时,返回上一级不兼容,安卓兼容 实现方法  (需要加return false) <a href="#" onclick="javascript: ...

  7. android仿ios滑动解锁,Android自定义绘制:Shader - 模仿iOS滑动解锁

    拖动进度条的时候,文字上有一坨类似光照的东西,闪闪的飘过去,类似 iOS 系统的 "滑动来解锁",  通过这篇文章介绍的 Shader ,可以很轻松的实现这种效果- 一.Shade ...

  8. android 仿苹果按钮,android 仿iphone 滑动开关按钮 switch

    [实例简介] 一个非常不错的仿iPhone滑动开关的控件, 适合项目需要的时候集成使用 [实例截图] [核心代码] 106633iPhone左右滑动开关键(设置) └── SlipButton ├── ...

  9. android高仿苹果计算器,Android仿IOS计算器源码

    [实例简介] 仿照IOS计算器开发一款Android计算器,可以实现四则运算和连续运算. [实例截图] [核心代码] cc455b24-185a-4894-84f5-471900c7cd01 └── ...

最新文章

  1. SharePoint Portal Server与SharePoint Services之间的关系
  2. python 2022/1/2
  3. word2vec原理(一): 词向量、CBOW与Skip-Gram模型基础
  4. 将一组数进行排序后,也输出他与之对应的序号
  5. java pkcs1转pkcs8_pkcs1与pkcs8格式RSA私钥互相转换
  6. http://bbs.winos.cn/viewthread.php?tid=1147extra=page=2
  7. 04.监控过程组-偏差分析
  8. 超赞Transformer+CNN=SOTA!
  9. Android Studio 2.2 HTTP proxy setting 提示异常
  10. addition过程 sgnb_5G NR接入优化问题排查思路
  11. python 多线程读写文件_Python多线程同步---文件读写控制方法
  12. 3.字符串(string)
  13. 在Windows 2008上安装SQL Server 2005
  14. 知到网课教师口语艺术考试题库(含答案)
  15. 死灰复燃的ThinkPad SL400 同机型与同问题可参考!也可帮忙排错!
  16. Qt 图片自适应QLabel大小
  17. 追问顶刊 | 独家专访《科学》最新研究:老年为何出现睡眠碎片化?
  18. 6、T5L DGUS ll 应用开发指南摘录(一)
  19. win10定时任务报错:操作员或系统管理员拒绝了请求
  20. visual assist x太卡了_带你纵横职场的高阶EVO笔记本 华硕灵耀X纵横评测

热门文章

  1. vue2 对接网易im初始化操作
  2. 浏览器适配IE浏览器问题
  3. 解决百度网盘安装系统权限限制问题
  4. Shell(Bash)
  5. item_password-获得淘口令真实url API调用说明
  6. golang channel
  7. 苹果发展到计算机,从天堂到地狱 十分钟看懂AIO兴衰存亡
  8. 最新《老男孩JAVA架构师之路成长课程》
  9. 脉冲神经元的建模与分析
  10. java web 分页详解2