ジェスチャーで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: 英語

