28 private static final int POINTER_ACTION_CURSOR = 0;
29 private static final int POINTER_ACTION_CLOSE = 3;
45 private static final int POINTER_ACTION_RCLICK = 2;
46 private static final int POINTER_ACTION_LCLICK = 4;
47 private static final int POINTER_ACTION_MOVE = 4;
48 private static final int POINTER_ACTION_SCROLL = 5;
49 private static final int POINTER_ACTION_RESET = 6;
50 private static final int POINTER_ACTION_KEYBOARD = 7;
51 private static final int POINTER_ACTION_EXTKEYBOARD = 8;
52 private static final float SCROLL_DELTA = 10.0f;
53 private static final int DEFAULT_TOUCH_POINTER_RESTORE_DELAY = 150;
54 private RectF pointerRect;
55 private final RectF[] pointerAreaRects =
new RectF[9];
56 private Matrix translationMatrix;
57 private boolean pointerMoving =
false;
58 private boolean pointerScrolling =
false;
60 private final Handler uiHandler =
new Handler(Looper.getMainLooper());
61 private final Runnable restorePointerImage =
62 () -> setPointerImage(R.drawable.touch_pointer_default);
64 private GestureDetector gestureDetector;
68 initTouchPointer(context);
73 super(context, attrs);
74 initTouchPointer(context);
79 super(context, attrs, defStyle);
80 initTouchPointer(context);
83 private void initTouchPointer(Context context)
86 new GestureDetector(context,
new TouchPointerGestureListener(),
null,
true);
87 gestureDetector.setLongPressTimeout(500);
88 translationMatrix =
new Matrix();
89 setScaleType(ScaleType.MATRIX);
90 setImageMatrix(translationMatrix);
93 final float rectSizeWidth = (float)getDrawable().getIntrinsicWidth() / 3.0f;
94 final float rectSizeHeight = (float)getDrawable().getIntrinsicWidth() / 3.0f;
95 for (
int i = 0; i < 3; i++)
97 for (
int j = 0; j < 3; j++)
99 int left = (int)(j * rectSizeWidth);
100 int top = (int)(i * rectSizeHeight);
101 int right = left + (int)rectSizeWidth;
102 int bottom = top + (int)rectSizeHeight;
103 pointerAreaRects[i * 3 + j] =
new RectF(left, top, right, bottom);
107 new RectF(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
112 this.listener = listener;
115 public int getPointerWidth()
117 return getDrawable().getIntrinsicWidth();
120 public int getPointerHeight()
122 return getDrawable().getIntrinsicHeight();
125 public float[] getPointerPosition()
127 float[] curPos =
new float[2];
128 translationMatrix.mapPoints(curPos);
132 private void movePointer(
float deltaX,
float deltaY)
134 translationMatrix.postTranslate(deltaX, deltaY);
135 setImageMatrix(translationMatrix);
138 private void ensureVisibility(
int screen_width,
int screen_height)
140 float[] curPos =
new float[2];
141 translationMatrix.mapPoints(curPos);
143 if (curPos[0] > (screen_width - pointerRect.width()))
144 curPos[0] = screen_width - pointerRect.width();
147 if (curPos[1] > (screen_height - pointerRect.height()))
148 curPos[1] = screen_height - pointerRect.height();
152 translationMatrix.setTranslate(curPos[0], curPos[1]);
153 setImageMatrix(translationMatrix);
156 private void displayPointerImageAction(
int resId)
158 setPointerImage(resId);
159 uiHandler.removeCallbacks(restorePointerImage);
160 uiHandler.postDelayed(restorePointerImage, DEFAULT_TOUCH_POINTER_RESTORE_DELAY);
163 private void setPointerImage(
int resId)
165 setImageResource(resId);
169 private RectF getCurrentPointerArea(
int area)
171 RectF transRect =
new RectF(pointerAreaRects[area]);
172 translationMatrix.mapRect(transRect);
176 private boolean pointerAreaTouched(MotionEvent event,
int area)
178 RectF transRect =
new RectF(pointerAreaRects[area]);
179 translationMatrix.mapRect(transRect);
180 return transRect.contains(event.getX(), event.getY());
183 private boolean pointerTouched(MotionEvent event)
185 RectF transRect =
new RectF(pointerRect);
186 translationMatrix.mapRect(transRect);
187 return transRect.contains(event.getX(), event.getY());
190 @Override
public boolean onTouchEvent(MotionEvent event)
193 if (!pointerMoving && !pointerScrolling && !pointerTouched(event))
195 return gestureDetector.onTouchEvent(event);
198 @Override
protected void onLayout(
boolean changed,
int left,
int top,
int right,
int bottom)
202 ensureVisibility(right - left, bottom - top);
207 void onTouchPointerClose();
209 void onTouchPointerLeftClick(
int x,
int y,
boolean down);
211 void onTouchPointerRightClick(
int x,
int y,
boolean down);
213 void onTouchPointerMove(
int x,
int y);
215 void onTouchPointerScroll(
boolean down);
217 void onTouchPointerToggleKeyboard();
219 void onTouchPointerToggleExtKeyboard();
221 void onTouchPointerResetScrollZoom();
224 private class TouchPointerGestureListener
extends GestureDetector.SimpleOnGestureListener
227 private MotionEvent prevEvent =
null;
229 public boolean onDown(MotionEvent e)
231 if (pointerAreaTouched(e, POINTER_ACTION_MOVE))
233 prevEvent = MotionEvent.obtain(e);
234 pointerMoving =
true;
236 else if (pointerAreaTouched(e, POINTER_ACTION_SCROLL))
238 prevEvent = MotionEvent.obtain(e);
239 pointerScrolling =
true;
240 setPointerImage(R.drawable.touch_pointer_scroll);
246 public boolean onUp(MotionEvent e)
248 if (prevEvent !=
null)
254 if (pointerScrolling)
255 setPointerImage(R.drawable.touch_pointer_default);
257 pointerMoving =
false;
258 pointerScrolling =
false;
262 public void onLongPress(MotionEvent e)
264 if (pointerAreaTouched(e, POINTER_ACTION_LCLICK))
266 setPointerImage(R.drawable.touch_pointer_active);
267 pointerMoving =
true;
268 RectF rect = getCurrentPointerArea(POINTER_ACTION_CURSOR);
269 listener.onTouchPointerLeftClick((
int)rect.centerX(), (
int)rect.centerY(),
true);
273 public void onLongPressUp(MotionEvent e)
277 setPointerImage(R.drawable.touch_pointer_default);
278 pointerMoving =
false;
279 RectF rect = getCurrentPointerArea(POINTER_ACTION_CURSOR);
280 listener.onTouchPointerLeftClick((
int)rect.centerX(), (
int)rect.centerY(),
false);
284 public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX,
float distanceY)
289 movePointer((
int)(e2.getX() - prevEvent.getX()),
290 (
int)(e2.getY() - prevEvent.getY()));
292 prevEvent = MotionEvent.obtain(e2);
295 RectF rect = getCurrentPointerArea(POINTER_ACTION_CURSOR);
296 listener.onTouchPointerMove((
int)rect.centerX(), (
int)rect.centerY());
299 else if (pointerScrolling)
302 float deltaY = e2.getY() - prevEvent.getY();
303 if (deltaY > SCROLL_DELTA)
305 listener.onTouchPointerScroll(
true);
307 prevEvent = MotionEvent.obtain(e2);
309 else if (deltaY < -SCROLL_DELTA)
311 listener.onTouchPointerScroll(
false);
313 prevEvent = MotionEvent.obtain(e2);
320 public boolean onSingleTapUp(MotionEvent e)
323 if (pointerAreaTouched(e, POINTER_ACTION_CLOSE))
324 listener.onTouchPointerClose();
325 else if (pointerAreaTouched(e, POINTER_ACTION_LCLICK))
327 displayPointerImageAction(R.drawable.touch_pointer_lclick);
328 RectF rect = getCurrentPointerArea(POINTER_ACTION_CURSOR);
329 listener.onTouchPointerLeftClick((
int)rect.centerX(), (
int)rect.centerY(),
true);
330 listener.onTouchPointerLeftClick((
int)rect.centerX(), (
int)rect.centerY(),
false);
332 else if (pointerAreaTouched(e, POINTER_ACTION_RCLICK))
334 displayPointerImageAction(R.drawable.touch_pointer_rclick);
335 RectF rect = getCurrentPointerArea(POINTER_ACTION_CURSOR);
336 listener.onTouchPointerRightClick((
int)rect.centerX(), (
int)rect.centerY(),
true);
337 listener.onTouchPointerRightClick((
int)rect.centerX(), (
int)rect.centerY(),
false);
339 else if (pointerAreaTouched(e, POINTER_ACTION_KEYBOARD))
341 displayPointerImageAction(R.drawable.touch_pointer_keyboard);
342 listener.onTouchPointerToggleKeyboard();
344 else if (pointerAreaTouched(e, POINTER_ACTION_EXTKEYBOARD))
346 displayPointerImageAction(R.drawable.touch_pointer_extkeyboard);
347 listener.onTouchPointerToggleExtKeyboard();
349 else if (pointerAreaTouched(e, POINTER_ACTION_RESET))
351 displayPointerImageAction(R.drawable.touch_pointer_reset);
352 listener.onTouchPointerResetScrollZoom();
358 public boolean onDoubleTap(MotionEvent e)
361 if (pointerAreaTouched(e, POINTER_ACTION_LCLICK))
363 RectF rect = getCurrentPointerArea(POINTER_ACTION_CURSOR);
364 listener.onTouchPointerLeftClick((
int)rect.centerX(), (
int)rect.centerY(),
true);
365 listener.onTouchPointerLeftClick((
int)rect.centerX(), (
int)rect.centerY(),
false);