11package com .unnamed .b .atv .view ;
22
33import android .annotation .SuppressLint ;
4+ import android .view .GestureDetector ;
45import android .view .HapticFeedbackConstants ;
56import android .view .MotionEvent ;
67import android .view .View ;
7- import android .view .ViewConfiguration ;
8+
9+ import androidx .annotation .NonNull ;
10+
811import com .unnamed .b .atv .model .TreeNode ;
912
1013class NodeTouchHandler implements View .OnTouchListener {
1114
1215 private final TreeNode node ;
1316 private final View view ;
1417 private final TreeNode .TreeNodeDragListener defaultDragListener ;
15- private final int touchSlop ;
16- private final long longPressTimeout ;
17-
18- private float startX , startY ;
19- private boolean isDragging = false ;
20- private boolean isLongPressFired = false ;
18+ private final GestureDetector gestureDetector ;
2119
22- private final Runnable longPressRunnable ;
20+ private boolean isAwaitingDrag = false ;
2321
2422 NodeTouchHandler (TreeNode node , View view , TreeNode .TreeNodeDragListener defaultDragListener ) {
2523 this .node = node ;
2624 this .view = view ;
2725 this .defaultDragListener = defaultDragListener ;
28- this .touchSlop = ViewConfiguration .get (view .getContext ()).getScaledTouchSlop ();
29- this .longPressTimeout = ViewConfiguration .getLongPressTimeout ();
30-
31- this .longPressRunnable = () -> {
32- isLongPressFired = true ;
33- this .view .performHapticFeedback (HapticFeedbackConstants .LONG_PRESS );
34- this .view .performLongClick ();
35- };
26+
27+ this .gestureDetector = new GestureDetector (view .getContext (), new GestureListener ());
28+ this .gestureDetector .setIsLongpressEnabled (true );
3629 }
3730
3831 @ SuppressLint ("ClickableViewAccessibility" )
3932 @ Override
4033 public boolean onTouch (View v , MotionEvent event ) {
41- switch (event .getAction ()) {
42- case MotionEvent .ACTION_DOWN :
43- startX = event .getX ();
44- startY = event .getY ();
45- isDragging = isLongPressFired = false ;
46- view .setPressed (true );
47- view .postDelayed (longPressRunnable , longPressTimeout );
48- return true ;
34+ gestureDetector .onTouchEvent (event );
4935
50- case MotionEvent .ACTION_MOVE :
51- if (isDragging || isLongPressFired ) break ;
52-
53- float dx = Math .abs (event .getX () - startX );
54- float dy = Math .abs (event .getY () - startY );
55-
56- if (dx > (touchSlop * 2 ) || dy > (touchSlop * 2 )) {
57- isDragging = true ;
58- cancelPendingAction ();
59- dispatchDrag ();
60- }
61- break ;
62-
63- case MotionEvent .ACTION_UP :
64- case MotionEvent .ACTION_CANCEL :
65- if (!isDragging && !isLongPressFired && event .getAction () == MotionEvent .ACTION_UP ) {
66- view .performClick ();
67- }
68- cancelPendingAction ();
69- break ;
36+ if (event .getAction () == MotionEvent .ACTION_UP || event .getAction () == MotionEvent .ACTION_CANCEL ) {
37+ isAwaitingDrag = false ;
38+ view .setPressed (false );
39+ } else if (event .getAction () == MotionEvent .ACTION_MOVE && isAwaitingDrag ) {
40+ isAwaitingDrag = false ;
41+ dispatchDrag ();
7042 }
71- return true ;
72- }
7343
74- private void cancelPendingAction () {
75- view .setPressed (false );
76- view .removeCallbacks (longPressRunnable );
44+ return true ;
7745 }
7846
7947 private void dispatchDrag () {
@@ -82,7 +50,37 @@ private void dispatchDrag() {
8250 : defaultDragListener ;
8351
8452 if (listener != null ) {
53+ view .performHapticFeedback (HapticFeedbackConstants .LONG_PRESS );
8554 listener .onStartDrag (node , node .getValue ());
8655 }
8756 }
57+
58+ private class GestureListener extends GestureDetector .SimpleOnGestureListener {
59+ @ Override
60+ public boolean onDown (@ NonNull MotionEvent e ) {
61+ view .setPressed (true );
62+ return true ;
63+ }
64+
65+ @ Override
66+ public boolean onSingleTapConfirmed (@ NonNull MotionEvent e ) {
67+ view .performClick ();
68+ return true ;
69+ }
70+
71+ @ Override
72+ public void onLongPress (@ NonNull MotionEvent e ) {
73+ view .performHapticFeedback (HapticFeedbackConstants .LONG_PRESS );
74+ view .performLongClick ();
75+ }
76+
77+ @ Override
78+ public boolean onDoubleTapEvent (MotionEvent e ) {
79+ if (e .getAction () == MotionEvent .ACTION_DOWN ) {
80+ isAwaitingDrag = true ;
81+ return true ;
82+ }
83+ return super .onDoubleTapEvent (e );
84+ }
85+ }
8886}
0 commit comments