ジェスチャーでWebViewのブラウザ履歴を行ったり来たりする
AndroidアプリはWebViewを使う事で簡単にブラウザ機能を追加する事が出来る。表示内容についてはあまり手を入れる事は出来ないが、UI回りについては割と自由に設計する事が可能だ。
今回は、WebViewに指を左右にスワイプするジェスチャーにより、閲覧履歴を前後に移動する機能の実装について説明しよう。
参考サイト:
http://blog.global-eng.co.jp/android/2011/02/11/gesturedetector...
http://wiki.livedoor.jp/moonlight_aska/d/...
ジェスチャーにはGestureDetectorクラスを利用する。本クラスを使う事により、左右のジェスチャーだけでなくダブルタップや長押しした際の動作も定義することが出来る。ただし、ブラウザ自体の操作を横取りしすぎない様注意が必要だ。
WebViewクラスを継承してカスタムWebViewを作成し、そこでジェスチャー処理を行う。下記サンプルでは指を左から右にスワイプする事で履歴を戻るが、戻る履歴が無い場合アプリ自体を終了する様にしている。
まずは、メインのActivity側。
private BackNotify mNotify = new BackNotify(); private Handler mNotifyHandler = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); nfWebView webview; webview = new nfWebView(this); //register handler for webview terminate notification if(mNotifyHandler == null) mNotifyHandler = new Handler(); webview.SetNotifyBackHandler(mNotifyHandler, mNotify); //add view RelativeLayout wholder = (RelativeLayout) findViewById(R.id.web); wholder.addView(webview, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT,RelativeLayout.LayoutParams.FILL_PARENT)); } //called when Back gesture is done while no more backward history public class BackNotify implements Runnable { //notify from nfWebView @Override public void run() { finish(); } }
カスタムWebViewクラス。ジェスチャーとして成立する指の移動量や速度も調整可能だ。
//custom webview public class nfWebView extends WebView { Context context; GestureDetector gd; int gesture_stx,gesture_sty; private Handler notifyback_handler; private Runnable notifyback_listener; public nfWebView(Context context) { super(context); this.context = context; gd = new GestureDetector(context, onGestureListener); } @Override public boolean onTouchEvent(MotionEvent event) { return (gd.onTouchEvent(event) || super.onTouchEvent(event)); } public void SetNotifyBackHandler(Handler _handler, Runnable _listener) { notifyback_handler = _handler; notifyback_listener = _listener; } public void CallNotifyBackTakenHandler() { notifyback_handler.post(notifyback_listener); } private final SimpleOnGestureListener onGestureListener = new SimpleOnGestureListener() { @Override public boolean onDoubleTap(MotionEvent e) { return super.onDoubleTap(e); } @Override public boolean onDoubleTapEvent(MotionEvent e) { return super.onDoubleTapEvent(e); } @Override public boolean onDown(MotionEvent e) { return super.onDown(e); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) { float deltax,deltay,velo; deltax = Math.abs(e1.getRawX()-e2.getRawX()); deltay = Math.abs(e1.getRawY()-e2.getRawY()); velo = Math.abs(velocityX); //pref_browser_gesturevelo is how fast finger moves. //pref_browser_gesturevelo set to 350 as default in my app if (deltax > 200 && deltay < 90 && velo > pref_browser_gesturevelo) { if (e1.getRawX() > e2.getRawX()) { if (canGoForward()){ //Gesture : move forward goForward(); } else{ //Gesture : no more forward history } } else if(e1.getRawX() < e2.getRawX()){ if (canGoBack()){ //Gesture : go back goBack(); } else{ //Gesture : no more backward history, end browser CallNotifyBackTakenHandler(); } } } return super.onFling(e1, e2, velocityX, velocityY); } @Override public void onLongPress(MotionEvent e) { super.onLongPress(e); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return super.onScroll(e1, e2, distanceX, distanceY); } @Override public void onShowPress(MotionEvent e) { super.onShowPress(e); } @Override public boolean onSingleTapConfirmed(MotionEvent e) { return super.onSingleTapConfirmed(e); } @Override public boolean onSingleTapUp(MotionEvent e) { return super.onSingleTapUp(e); } }; }
This post is also available in: 英語