GWT ScrollPanel for Touch Screens

Getting this working is easier than you think. Basically the only tricky bit is that the touch object allows for multiple fingers they are represented in the array ‘touches[]‘. Since we are only scrolling we only need to worry about the first finger which is why I use touches[0].screenY. Enjoy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package com.peterfranza.gwt.mobileui.client.widgets;
 
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.ui.ScrollPanel;
 
/**
 * 
 * @author peter.franza
 *
 */
public class TouchScrollPanel extends ScrollPanel {
 
	private int initialTouchX = -1;
	private int initialTouchY = -1;
	private int initialHorizontalOffset;
	private int initialVerticalOffset;
	private boolean moved = false;
 
	{
		attachTouch(getElement());
	}
 
	public TouchScrollPanel(VerticalPanel body) {
		super(body);
	}
 
	private native void attachTouch(JavaScriptObject ele) /*-{	
		var ref = this;
		ele.ontouchstart = function(evt){
	  		evt.preventDefault();	
	  		ref.@com.orci.datagateway.OpenIMWeb.mobile.client.widgets.TouchScrollPanel::setInitialTouch(II)(evt.touches[0].screenX, evt.touches[0].screenY);
		}	
		ele.ontouchmove = function(evt){
	  		evt.preventDefault();	
	  		ref.@com.orci.datagateway.OpenIMWeb.mobile.client.widgets.TouchScrollPanel::doScroll(II)(evt.touches[0].screenX, evt.touches[0].screenY);
		}		
		ele.ontouchend = function(evt){
			evt.preventDefault();
			ref.@com.orci.datagateway.OpenIMWeb.mobile.client.widgets.TouchScrollPanel::setEndTouch(II)(evt.pageX, evt.pageY);
		}		
	}-*/;
 
	private native void fireClick(int x, int y) /*-{	
		var theTarget = $doc.elementFromPoint(x, y);
		if (theTarget.nodeType == 3) theTarget = theTarget.parentNode;
 
		var theEvent = $doc.createEvent('MouseEvents');
		theEvent.initEvent('click', true, true);
		theTarget.dispatchEvent(theEvent);
	}-*/;
 
 
	@SuppressWarnings("unused")
	private void setInitialTouch(int x, int y) {
		initialVerticalOffset = getScrollPosition();
		initialHorizontalOffset = getHorizontalScrollPosition();
 
		initialTouchX = x;
		initialTouchY = y;
		moved = false;
 
	}
 
	@SuppressWarnings("unused")
	private void doScroll(int x, int y) {
		if (initialTouchY != -1) {
			moved = true;
			int vDelta = initialTouchY - y;
			int hDelta = initialTouchX - x;
			setScrollPosition(vDelta + initialVerticalOffset);
			setHorizontalScrollPosition(hDelta + initialHorizontalOffset);
		}
	}
 
	@SuppressWarnings("unused")
	private void setEndTouch(int x, int y) {
		if (!moved) {
			fireClick(x, y);
		}
		initialTouchX = -1;
		initialTouchY = -1;
	} 
}


Did you enjoy this post? Why not leave a comment below and continue the conversation, or subscribe to my feed and get articles like this delivered automatically to your feed reader.

Comments

I’ve updated this post so the scroll will propagate click events if the touch doesn’t move

Reply

Updated to also allow horizontal scrolling.
— Contributed by b.sciacchitano

Reply

“ref.@com.orci.datagateway.OpenIMWeb.mobile.client.widgets.TouchScrollPanel::setInitialTouch(II)(evt.touches[0].screenX, evt.touches[0].screenY);”

?

Reply

Leave a comment

(required)

(required)