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 交互中值返回的問題