Skip to content

Commit b478a00

Browse files
committed
Add multi-touch
1 parent 22bea65 commit b478a00

File tree

10 files changed

+126
-67
lines changed

10 files changed

+126
-67
lines changed

AndroidUIDemo/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
android:versionCode="1"
44
android:versionName="1.0.0" package="com.oreilly.demo.android.pa.uidemo">
5-
<uses-sdk android:targetSdkVersion="14"></uses-sdk>
5+
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="14" />
66
<application android:icon="@drawable/icon" android:label="@string/app_name">
77
<activity android:name=".TouchMe"
88
android:label="@string/app_name">

AndroidUIDemo/project.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
# project structure.
99

1010
# Project target.
11-
target=android-14
11+
target=android-8
842 Bytes
Loading
842 Bytes
Loading

AndroidUIDemo/res/layout/main.xml

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
32
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
43
android:id="@+id/root"
54
android:orientation="vertical"
65
android:gravity="center_horizontal"
76
android:background="@drawable/lt_grey"
87
android:layout_width="match_parent"
9-
android:layout_height="wrap_content">
8+
android:layout_height="wrap_content"
9+
android:baselineAligned="false">
1010

11+
<com.oreilly.demo.android.pa.uidemo.view.DotView
12+
android:id="@+id/dots"
13+
android:focusableInTouchMode="true"
14+
android:layout_width="match_parent"
15+
android:layout_height="match_parent"
16+
android:layout_weight="1"
17+
android:background="@drawable/white"
18+
/>
19+
1120
<LinearLayout
1221
android:orientation="horizontal"
1322
android:background="@drawable/grey"
@@ -18,16 +27,16 @@
1827
android:id="@+id/text1"
1928
android:text="@string/defaultText"
2029
android:focusable="false"
21-
android:layout_width="wrap_content"
2230
android:layout_height="wrap_content"
31+
android:layout_width="0dp"
2332
android:layout_weight="1"/>
2433

2534
<EditText
2635
android:id="@+id/text2"
2736
android:text="@string/defaultText"
2837
android:focusable="false"
29-
android:layout_width="wrap_content"
3038
android:layout_height="wrap_content"
39+
android:layout_width="0dp"
3140
android:layout_weight="1"/>
3241
</LinearLayout>
3342

@@ -41,16 +50,16 @@
4150
android:id="@+id/button1"
4251
android:text="@string/labelRed"
4352
android:textColor="@drawable/red"
44-
android:layout_width="wrap_content"
4553
android:layout_height="wrap_content"
54+
android:layout_width="0dp"
4655
android:layout_weight="1"/>
4756

4857
<Button
4958
android:id="@+id/button2"
5059
android:text="@string/labelGreen"
5160
android:textColor="@drawable/green"
52-
android:layout_width="wrap_content"
5361
android:layout_height="wrap_content"
62+
android:layout_width="0dp"
5463
android:layout_weight="1"/>
5564
</LinearLayout>
5665
</LinearLayout>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<menu xmlns:android="http://schemas.android.com/apk/res/android">
3+
<item android:id="@+id/menu_clear"
4+
android:title="@string/menuClear"
5+
/>
6+
7+
<!-- ICS
8+
android:icon="@drawable/trashcan"
9+
android:showAsAction="ifRoom|withText"
10+
/>
11+
-->
12+
</menu>

AndroidUIDemo/res/values/colors.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66
<drawable name="lt_grey">#dddddd</drawable>
77
<drawable name="grey">#999999</drawable>
88
<drawable name="dk_grey">#666666</drawable>
9+
<drawable name="white">#ffffffff</drawable>
910
</resources>

AndroidUIDemo/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44
<string name="defaultText">0</string>
55
<string name="labelRed">Red</string>
66
<string name="labelGreen">Green</string>
7+
<string name="menuClear">Clear</string>
78
</resources>

AndroidUIDemo/src/com/oreilly/demo/android/pa/uidemo/TouchMe.java

Lines changed: 64 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.oreilly.demo.android.pa.uidemo;
22

3+
import java.util.ArrayList;
4+
import java.util.List;
35
import java.util.Random;
46

57
import android.app.Activity;
@@ -17,8 +19,6 @@
1719
import android.view.View.OnKeyListener;
1820
import android.widget.Button;
1921
import android.widget.EditText;
20-
import android.widget.LinearLayout;
21-
2222
import com.oreilly.demo.android.pa.uidemo.model.Dot;
2323
import com.oreilly.demo.android.pa.uidemo.model.Dots;
2424
import com.oreilly.demo.android.pa.uidemo.view.DotView;
@@ -36,35 +36,57 @@ private static final class TrackingTouchListener
3636
implements View.OnTouchListener
3737
{
3838
private final Dots mDots;
39+
private List<Integer> tracks = new ArrayList<Integer>();
3940

4041
TrackingTouchListener(Dots dots) { mDots = dots; }
4142

4243
@Override public boolean onTouch(View v, MotionEvent evt) {
43-
switch (evt.getAction()) {
44+
int n;
45+
int idx;
46+
int action = evt.getAction();
47+
switch (action & MotionEvent.ACTION_MASK) {
4448
case MotionEvent.ACTION_DOWN:
49+
case MotionEvent.ACTION_POINTER_DOWN:
50+
idx = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
51+
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
52+
tracks.add(Integer.valueOf(evt.getPointerId(idx)));
53+
break;
54+
55+
case MotionEvent.ACTION_POINTER_UP:
56+
idx = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
57+
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
58+
tracks.remove(Integer.valueOf(evt.getPointerId(idx)));
4559
break;
4660

4761
case MotionEvent.ACTION_MOVE:
48-
for (int i = 0, n = evt.getHistorySize(); i < n; i++) {
49-
addDot(
50-
mDots,
51-
evt.getHistoricalX(i),
52-
evt.getHistoricalY(i),
53-
evt.getHistoricalPressure(i),
54-
evt.getHistoricalSize(i));
62+
n = evt.getHistorySize();
63+
for (Integer i: tracks) {
64+
idx = evt.findPointerIndex(i.intValue());
65+
for (int j = 0; j < n; j++) {
66+
addDot(
67+
mDots,
68+
evt.getHistoricalX(idx, j),
69+
evt.getHistoricalY(idx, j),
70+
evt.getHistoricalPressure(idx, j),
71+
evt.getHistoricalSize(idx, j));
72+
}
5573
}
5674
break;
5775

76+
5877
default:
5978
return false;
6079
}
6180

62-
addDot(
63-
mDots,
64-
evt.getX(),
65-
evt.getY(),
66-
evt.getPressure(),
67-
evt.getSize());
81+
for (Integer i: tracks) {
82+
idx = evt.findPointerIndex(i.intValue());
83+
addDot(
84+
mDots,
85+
evt.getX(idx),
86+
evt.getY(idx),
87+
evt.getPressure(idx),
88+
evt.getSize(idx));
89+
}
6890

6991
return true;
7092
}
@@ -124,35 +146,38 @@ public void run() {
124146
@Override public void onCreate(Bundle state) {
125147
super.onCreate(state);
126148

127-
dotView = new DotView(this, dotModel);
128-
dotView.setOnCreateContextMenuListener(this);
129-
130149
// install the view
131150
setContentView(R.layout.main);
132-
((LinearLayout) findViewById(R.id.root)).addView(dotView, 0);
133151

152+
// find the dots view
153+
dotView = (DotView) findViewById(R.id.dots);
154+
dotView.setDots(dotModel);
155+
156+
dotView.setOnCreateContextMenuListener(this);
134157
dotView.setOnTouchListener(new TrackingTouchListener(dotModel));
135158

136159
dotView.setOnKeyListener(new OnKeyListener() {
137160
@Override
138161
public boolean onKey(View v, int keyCode, KeyEvent event) {
139-
if (KeyEvent.ACTION_UP != event.getAction()) {
140-
int color = Color.BLUE;
141-
switch (keyCode) {
142-
case KeyEvent.KEYCODE_SPACE:
143-
color = Color.MAGENTA;
144-
break;
145-
case KeyEvent.KEYCODE_ENTER:
146-
color = Color.YELLOW;
147-
break;
148-
default: ;
149-
}
162+
if (KeyEvent.ACTION_DOWN != event.getAction()) {
163+
return false;
164+
}
150165

151-
makeDot(dotModel, dotView, color);
166+
int color;
167+
switch (keyCode) {
168+
case KeyEvent.KEYCODE_SPACE:
169+
color = Color.MAGENTA;
170+
break;
171+
case KeyEvent.KEYCODE_ENTER:
172+
color = Color.BLUE;
173+
break;
174+
default:
175+
return false;
152176
}
153177

154-
return (keyCode < KeyEvent.KEYCODE_0)
155-
||(keyCode > KeyEvent.KEYCODE_9);
178+
makeDot(dotModel, dotView, color);
179+
return true;
180+
156181
} });
157182

158183

@@ -194,22 +219,20 @@ else if (hasFocus && (null == dotGenerator)) {
194219

195220
/** Install an options menu. */
196221
@Override public boolean onCreateOptionsMenu(Menu menu) {
197-
super.onCreateOptionsMenu(menu);
198-
menu.add(Menu.NONE, 1, Menu.NONE, "Clear")
199-
.setAlphabeticShortcut('x');
222+
getMenuInflater().inflate(R.menu.simple_menu, menu);
200223
return true;
201224
}
202225

203226
/** Respond to an options menu selection. */
204227
@Override public boolean onOptionsItemSelected(MenuItem item) {
205228
switch (item.getItemId()) {
206-
case 1:
229+
case R.id.menu_clear:
207230
dotModel.clearDots();
208231
return true;
209-
default: ;
210-
}
211232

212-
return false;
233+
default:
234+
return super.onOptionsItemSelected(item);
235+
}
213236
}
214237

215238
/** Install a context menu. */

AndroidUIDemo/src/com/oreilly/demo/android/pa/uidemo/view/DotView.java

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import android.graphics.Color;
77
import android.graphics.Paint;
88
import android.graphics.Paint.Style;
9-
9+
import android.util.AttributeSet;
1010
import android.view.View;
1111

1212
import com.oreilly.demo.android.pa.uidemo.model.Dot;
@@ -19,41 +19,54 @@
1919
* @author <a href="mailto:[email protected]">Blake Meike</a>
2020
*/
2121
public class DotView extends View {
22-
private final Dots dots;
22+
23+
private volatile Dots dots;
2324

2425
/**
2526
* @param context the rest of the application
26-
* @param dots the dots we draw
2727
*/
28-
public DotView(Context context, Dots dots) {
28+
public DotView(Context context) {
2929
super(context);
30-
this.dots = dots;
31-
setMinimumWidth(180);
32-
setMinimumHeight(200);
33-
setFocusable(true);
30+
setFocusableInTouchMode(true);
3431
}
35-
32+
33+
/**
34+
* @param context
35+
* @param attrs
36+
*/
37+
public DotView(Context context, AttributeSet attrs) {
38+
super(context, attrs);
39+
setFocusableInTouchMode(true);
40+
}
41+
3642
/**
37-
* @see android.view.View#onMeasure(int, int)
43+
* @param context
44+
* @param attrs
45+
* @param defStyle
3846
*/
39-
@Override
40-
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
41-
setMeasuredDimension(
42-
getSuggestedMinimumWidth(),
43-
getSuggestedMinimumHeight());
47+
public DotView(Context context, AttributeSet attrs, int defStyle) {
48+
super(context, attrs, defStyle);
49+
setFocusableInTouchMode(true);
4450
}
4551

52+
/**
53+
* @param dots
54+
*/
55+
public void setDots(Dots dots) { this.dots = dots; }
56+
4657
/**
4758
* @see android.view.View#onDraw(android.graphics.Canvas)
4859
*/
4960
@Override protected void onDraw(Canvas canvas) {
50-
canvas.drawColor(Color.WHITE);
51-
61+
//canvas.drawColor(Color.WHITE);
62+
5263
Paint paint = new Paint();
5364
paint.setStyle(Style.STROKE);
5465
paint.setColor(hasFocus() ? Color.BLUE : Color.GRAY);
5566
canvas.drawRect(0, 0, getWidth() - 1, getHeight() -1, paint);
56-
67+
68+
if (null == dots) { return; }
69+
5770
paint.setStyle(Style.FILL);
5871
for (Dot dot : dots.getDots()) {
5972
paint.setColor(dot.getColor());

0 commit comments

Comments
 (0)