Program Resource

Resource libraries for programmers and developers

It is easy to add Web functionality to Android app using WebView. It is hard to customize contents shown inside webview, but you can customize UIs.

This time, I’m going to show how to use gesture, swiping finger left / right to go back / forward in webview history.

GestureDetector class is used for gesture processing. By using this class, not only left / right swipe but also double tap or long hold can be assigned to some functions. Be careful not to override too much of  browser functions.

Use WebView class as base, and create custom WebView class to handle gesture. In sample code below, swiping finger left to right goes back in history, but if there are no more backward history, it will finish app.

First, main 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();
	}
}

Custom WebView class. You can adjust how far and how fast finger hat to be tripped to make gesture effective.

//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: Japanese

Leave a Reply

Your email address will not be published. Required fields are marked *


*