hybrid 开发关于手势的思考
手势非常总要,尤其是在app应用中,大量的app提供的右滑退出等功能培养了用户习惯,所以我们在开发app的时候考虑到用户体验最好也要加入类似功能,但是具体到app 中或者是hybrid 下的webview 中,里边可很有可能需要处理横向滚动处理,例如广告,iscroll 控件,swiper 控件,等等也会需要横向滑动手势,如果做到两个互不干扰,这是需要我们思考的一个问题,下图就是一个带有滑动切换广告的banner ,
想解决这个问题,android 是否原始支持手势退出,这个我研究一下好像没有原生接口来支持,这样一来我们就需要通过自己实现功能来处理滑动退出,参考了一下主流app 的操作习惯,但是我们需要考虑几点,首要问题就是如何判断用户意图是要退出当前页面,通过对其他app和ios 一些应用的研究,当用户从屏幕最左侧作为起始点滑动的时候是明显具有退出意图,所以,我们可以以此作为核心参考依据,划定一个滑动范围作为退出条件
1.滑动起始范围
2.滑动速度
因为android只有2d接口所以没法判断用户按压的力度,只能通过二维的手势做简单的判断
这里我们需要一个android skd 中一个 非常总要跟用户点击操作有关的接口
gestureDetector=new GestureDetector(GestureTest1Activity.this,onGestureListener);
/**
@param e1 :起始移动点
@param e2 :结束时的移动点
@param velocityX x轴的移动速度
@param velocityY y轴的移动速度
*/
public boolean onFling(android.view.MotionEvent e1, android.view.MotionEvent e2, float velocityX, float velocityY) {
System.out.println("onFling................");
float x = e2.getX() - e1.getX();//滑动后的x值减去滑动前的x值 就是滑动的横向水平距离(x)
float y = e2.getY() - e1.getY();//滑动后的y值减去滑动前的y值 就是滑动的纵向垂直距离(y)
float startX=e1.getX();
System.out.println(e1.getX()+"~~~~~~~~~~~~~~~~~~~~~~");
//如果滑动的横向距离大于100,表明是右滑了,那么就执行下面的方法,可以是关闭当前的activity
if (x > 100&&startX<15) {
doResult(RIGHT);
Log.w("tag", "RIGHT>" + x);
}
//如果滑动的横向距离大于100,表明是左滑了(因为左滑为负数,所以距离大于100就是x值小于-100)
if (x < -100) {
Log.w("tag", "LEFT>" + x);
doResult(LEFT);
}
return true;
}
GestureDetector 中有很多跟手势相关的接口例如
onFling 和点,滑动 有关,包含 touch start ,touch move ,touch end
onDoubleTap 双击相关
onScroll 滑动相关
这样我们就开发完成android native 下关于右滑退出的功能,这里需要有个概念就是,activity 的事件
分发机制。
@Override public boolean dispatchTouchEvent(android.view.MotionEvent event) { // 在事件分发中把事件传给手势组件处理 return gestureDetector.onTouchEvent(event); }
当我们希望使用手势相关的功能时候都要处理这个事件分发,重写dispatchTouchEvent 把事件分发中的event 交给 gestureDetector 处理,
这里我简单描述一下android的事件分发机制,android 的事件机制,与浏览器的事件有所不同
浏览器的事件传播机制的核心是基于事件捕获,和事件冒泡
android 的事件传播机制是基于事件分发,分发器处理是在activity 上,
为什么需要这个事件机制处理,而且地位非常重要处于核心位置,我们深层思考不管是web,还是android 的view 都是一个视觉是二维,本质是三维的结构,如果view 本质都是二维的话,那么事件机制就没那么重要了,因为没有父子关系也就没有了事件传播,独立view 没有相互关系也缺乏传播的依据,我们在开发view 的时候不管是div 的嵌套关系,还是android RelativeLayout 都是父子嵌套的关系,
和android 的事件系统作对比
其实很相像。
所以我们只需要在activity 中做手势处理,其他子组件做正常事件分发,这样就能既满足整个activity 的右滑手势退出,而且webview 中的其他事件也能正常运行
@Override public boolean dispatchTouchEvent(android.view.MotionEvent event) { // 調用父級會自動分發事件,否則字控件就沒有事件響應了, super.dispatchTouchEvent(event); switch (event.getAction()) { case android.view.MotionEvent.ACTION_SCROLL : System.out.println("scroll................................"); break; case android.view.MotionEvent.ACTION_DOWN: System.out.println("ACTION_DOWN................................"); break; case android.view.MotionEvent.ACTION_MOVE : System.out.println("ACTION_MOVE................................"); break; case android.view.MotionEvent.ACTION_UP : System.out.println("ACTION_UP................................"); break; default: break; } //wv.onTouchEvent(event); return gestureDetector.onTouchEvent(event); };
注:在重写dispatchTouchEvent 事件时候一定要调用 super.dispatchTouchEvent(event); 父类正常的事件分发,否则我们重写的事件分发原始正常的分发过程就中断了,
我们也可以封装成一个JavaScriptInterface 接口暴露给webview 的js 使用,可以让用户通过设置来选择这个activity 是否支持手势退出
Hybird 开发中有很多地方需要处理
1.native 渲染和webview 中渲染不同步,大量的hybrid应用中会使用头部native ,内容webview 导致很多设置会不生效
2.js 的缓存管理 例如localstorage 和缓存的js文件
3.跳转路径管理,传参等问题
4.js hybrid 交互中值返回的问题