35
35
* <p/>
36
36
* Currently, no error-checking is done on standard {@link #addView(android.view.View)} and
37
37
* {@link #removeView(android.view.View)} calls, so avoid using these with children previously
38
- * declared as draggable to prevent memory leaks and/or subtle bugs.
39
- * <p/>
40
- * Apologies - this class is neither clear nor readable. Maybe someday. But it works!
38
+ * declared as draggable to prevent memory leaks and/or subtle bugs. Pull requests welcome!
41
39
*/
42
40
public class DragLinearLayout extends LinearLayout {
43
41
private static final String LOG_TAG = "DragLinearLayout" ;
@@ -89,10 +87,10 @@ public void cancelExistingAnimation() {
89
87
* Holds state information about the currently dragged item.
90
88
* <p/>
91
89
* Rough lifecycle:
92
- * <li>#setValidOnPossibleDrag - #valid == true</li>
90
+ * <li>#startDetectingOnPossibleDrag - #detecting == true</li>
93
91
* <li> if drag is recognised, #onDragStart - #dragging == true</li>
94
92
* <li> if drag ends, #onDragStop - #dragging == false, #settling == true</li>
95
- * <li>if gesture ends without drag, or settling finishes, #setInvalid - #valid == false</li>
93
+ * <li>if gesture ends without drag, or settling finishes, #stopDetecting - #detecting == false</li>
96
94
*/
97
95
private class DragItem {
98
96
private View view ;
@@ -105,14 +103,14 @@ private class DragItem {
105
103
private int targetTopOffset ;
106
104
private ValueAnimator settleAnimation ;
107
105
108
- private boolean valid ;
106
+ private boolean detecting ;
109
107
private boolean dragging ;
110
108
111
109
public DragItem () {
112
- setInvalid ();
110
+ stopDetecting ();
113
111
}
114
112
115
- public void setValidOnPossibleDrag (final View view , final int position ) {
113
+ public void startDetectingOnPossibleDrag (final View view , final int position ) {
116
114
this .view = view ;
117
115
this .startVisibility = view .getVisibility ();
118
116
this .viewDrawable = getDragDrawable (view );
@@ -123,7 +121,7 @@ public void setValidOnPossibleDrag(final View view, final int position) {
123
121
this .targetTopOffset = 0 ;
124
122
this .settleAnimation = null ;
125
123
126
- this .valid = true ;
124
+ this .detecting = true ;
127
125
}
128
126
129
127
public void onDragStart () {
@@ -148,8 +146,8 @@ public boolean settling() {
148
146
return null != settleAnimation ;
149
147
}
150
148
151
- public void setInvalid () {
152
- this .valid = false ;
149
+ public void stopDetecting () {
150
+ this .detecting = false ;
153
151
if (null != view ) view .setVisibility (startVisibility );
154
152
view = null ;
155
153
startVisibility = -1 ;
@@ -165,7 +163,7 @@ public void setInvalid() {
165
163
}
166
164
167
165
/**
168
- * The currently dragged item, if {@link com.jmedeisis.draglinearlayout.DragLinearLayout.DragItem#valid }.
166
+ * The currently dragged item, if {@link com.jmedeisis.draglinearlayout.DragLinearLayout.DragItem#detecting }.
169
167
*/
170
168
private final DragItem draggedItem ;
171
169
private final int slop ;
@@ -338,17 +336,18 @@ private long getTranslateAnimationDuration(float distance) {
338
336
339
337
/**
340
338
* Initiates a new {@link #draggedItem} unless the current one is still
341
- * {@link com.jmedeisis.draglinearlayout.DragLinearLayout.DragItem#valid }.
339
+ * {@link com.jmedeisis.draglinearlayout.DragLinearLayout.DragItem#detecting }.
342
340
*/
343
341
private void startDetectingDrag (View child ) {
344
- if (draggedItem .valid ) return ; // existing drag in process, only one at a time is allowed
342
+ if (draggedItem .detecting )
343
+ return ; // existing drag in process, only one at a time is allowed
345
344
346
345
final int position = indexOfChild (child );
347
346
348
347
// complete any existing animations, both for the newly selected child and the previous dragged one
349
348
draggableChildren .get (position ).endExistingAnimation ();
350
349
351
- draggedItem .setValidOnPossibleDrag (child , position );
350
+ draggedItem .startDetectingOnPossibleDrag (child , position );
352
351
}
353
352
354
353
private void startDrag () {
@@ -359,14 +358,14 @@ private void startDrag() {
359
358
/**
360
359
* Animates the dragged item to its final resting position.
361
360
*/
362
- private void stopDrag () {
361
+ private void onDragStop () {
363
362
draggedItem .settleAnimation = ValueAnimator .ofFloat (draggedItem .totalDragOffset ,
364
363
draggedItem .totalDragOffset - draggedItem .targetTopOffset )
365
364
.setDuration (getTranslateAnimationDuration (draggedItem .targetTopOffset ));
366
365
draggedItem .settleAnimation .addUpdateListener (new ValueAnimator .AnimatorUpdateListener () {
367
366
@ Override
368
367
public void onAnimationUpdate (ValueAnimator animation ) {
369
- if (!draggedItem .valid ) return ; // already stopped
368
+ if (!draggedItem .detecting ) return ; // already stopped
370
369
371
370
draggedItem .setTotalOffset (((Float ) animation .getAnimatedValue ()).intValue ());
372
371
@@ -384,12 +383,12 @@ public void onAnimationStart(Animator animation) {
384
383
385
384
@ Override
386
385
public void onAnimationEnd (Animator animation ) {
387
- if (!draggedItem .valid ) {
386
+ if (!draggedItem .detecting ) {
388
387
return ; // already stopped
389
388
}
390
389
391
390
draggedItem .settleAnimation = null ;
392
- draggedItem .setInvalid ();
391
+ draggedItem .stopDetecting ();
393
392
394
393
if (null != dragTopShadowDrawable ) dragTopShadowDrawable .setAlpha (255 );
395
394
dragBottomShadowDrawable .setAlpha (255 );
@@ -491,7 +490,7 @@ public boolean onPreDraw() {
491
490
Log .d (LOG_TAG , "Updating settle animation" );
492
491
draggedItem .settleAnimation .removeAllListeners ();
493
492
draggedItem .settleAnimation .cancel ();
494
- stopDrag ();
493
+ onDragStop ();
495
494
}
496
495
return true ;
497
496
}
@@ -555,7 +554,7 @@ private static float smootherStep(float edge1, float edge2, float val) {
555
554
protected void dispatchDraw (@ NonNull Canvas canvas ) {
556
555
super .dispatchDraw (canvas );
557
556
558
- if (draggedItem .valid && (draggedItem .dragging || draggedItem .settling ())) {
557
+ if (draggedItem .detecting && (draggedItem .dragging || draggedItem .settling ())) {
559
558
canvas .save ();
560
559
canvas .translate (0 , draggedItem .totalDragOffset );
561
560
draggedItem .viewDrawable .draw (canvas );
@@ -583,37 +582,37 @@ protected void dispatchDraw(@NonNull Canvas canvas) {
583
582
* 1) User taps outside any children.
584
583
* #onInterceptTouchEvent receives DOWN
585
584
* #onTouchEvent receives DOWN
586
- * draggedItem.valid == false, we return false and no further events are received
585
+ * draggedItem.detecting == false, we return false and no further events are received
587
586
* 2) User taps on non-interactive drag handle / child, e.g. TextView or ImageView.
588
587
* #onInterceptTouchEvent receives DOWN
589
588
* DragHandleOnTouchListener (attached to each draggable child) #onTouch receives DOWN
590
- * #startDetectingDrag is called, draggedItem is now valid
589
+ * #startDetectingDrag is called, draggedItem is now detecting
591
590
* view does not handle touch, so our #onTouchEvent receives DOWN
592
- * draggedItem.valid == true, we #startDrag() and proceed to handle the drag
591
+ * draggedItem.detecting == true, we #startDrag() and proceed to handle the drag
593
592
* 3) User taps on interactive drag handle / child, e.g. Button.
594
593
* #onInterceptTouchEvent receives DOWN
595
594
* DragHandleOnTouchListener (attached to each draggable child) #onTouch receives DOWN
596
- * #startDetectingDrag is called, draggedItem is now valid
595
+ * #startDetectingDrag is called, draggedItem is now detecting
597
596
* view handles touch, so our #onTouchEvent is not called yet
598
597
* #onInterceptTouchEvent receives ACTION_MOVE
599
598
* if dy > touch slop, we assume user wants to drag and intercept the event
600
599
* #onTouchEvent receives further ACTION_MOVE events, proceed to handle the drag
601
600
*
602
601
* For cases 2) and 3), lifting the active pointer at any point in the sequence of events
603
- * triggers #onTouchEnded and the draggedItem, if valid , is #setInvalid .
602
+ * triggers #onTouchEnd and the draggedItem, if detecting , is #stopDetecting .
604
603
*/
605
604
606
605
@ Override
607
606
public boolean onInterceptTouchEvent (MotionEvent event ) {
608
607
switch (MotionEventCompat .getActionMasked (event )) {
609
608
case MotionEvent .ACTION_DOWN : {
610
- if (draggedItem .valid ) return false ; // an existing item is (likely) settling
609
+ if (draggedItem .detecting ) return false ; // an existing item is (likely) settling
611
610
downY = (int ) MotionEventCompat .getY (event , 0 );
612
611
activePointerId = MotionEventCompat .getPointerId (event , 0 );
613
612
break ;
614
613
}
615
614
case MotionEvent .ACTION_MOVE : {
616
- if (!draggedItem .valid ) return false ;
615
+ if (!draggedItem .detecting ) return false ;
617
616
if (INVALID_POINTER_ID == activePointerId ) break ;
618
617
final int pointerIndex = event .findPointerIndex (activePointerId );
619
618
final float y = MotionEventCompat .getY (event , pointerIndex );
@@ -633,9 +632,9 @@ public boolean onInterceptTouchEvent(MotionEvent event) {
633
632
}
634
633
case MotionEvent .ACTION_CANCEL :
635
634
case MotionEvent .ACTION_UP : {
636
- onTouchEnded ();
635
+ onTouchEnd ();
637
636
638
- if (draggedItem .valid ) draggedItem .setInvalid ();
637
+ if (draggedItem .detecting ) draggedItem .stopDetecting ();
639
638
break ;
640
639
}
641
640
}
@@ -647,7 +646,7 @@ public boolean onInterceptTouchEvent(MotionEvent event) {
647
646
public boolean onTouchEvent (@ NonNull MotionEvent event ) {
648
647
switch (MotionEventCompat .getActionMasked (event )) {
649
648
case MotionEvent .ACTION_DOWN : {
650
- if (!draggedItem .valid || draggedItem .settling ()) return false ;
649
+ if (!draggedItem .detecting || draggedItem .settling ()) return false ;
651
650
startDrag ();
652
651
return true ;
653
652
}
@@ -671,16 +670,20 @@ public boolean onTouchEvent(@NonNull MotionEvent event) {
671
670
}
672
671
case MotionEvent .ACTION_CANCEL :
673
672
case MotionEvent .ACTION_UP : {
674
- onTouchEnded ();
673
+ onTouchEnd ();
675
674
676
- if (draggedItem .dragging ) stopDrag (); // TODO test whether check necessary
675
+ if (draggedItem .dragging ) {
676
+ onDragStop ();
677
+ } else if (draggedItem .detecting ) {
678
+ draggedItem .stopDetecting ();
679
+ }
677
680
return true ;
678
681
}
679
682
}
680
683
return false ;
681
684
}
682
685
683
- private void onTouchEnded () {
686
+ private void onTouchEnd () {
684
687
downY = -1 ;
685
688
activePointerId = INVALID_POINTER_ID ;
686
689
}
0 commit comments