11
11
import androidx .core .view .GestureDetectorCompat ;
12
12
import androidx .core .view .ViewCompat ;
13
13
import androidx .interpolator .view .animation .FastOutLinearInInterpolator ;
14
+
15
+ import android .os .Handler ;
16
+ import android .os .Looper ;
14
17
import android .text .*;
15
18
import android .text .format .DateFormat ;
16
19
import android .text .style .StyleSpan ;
@@ -38,6 +41,9 @@ private enum Direction {
38
41
private enum NewEventScrollDirection {
39
42
NONE , UP , DOWN
40
43
}
44
+ private enum AutoScrollDirection {
45
+ LEFT , RIGHT
46
+ }
41
47
42
48
@ Deprecated
43
49
public static final int LENGTH_SHORT = 1 ;
@@ -94,6 +100,13 @@ private enum NewEventScrollDirection {
94
100
private boolean movingNewEvent = false ;
95
101
private NewEventScrollDirection mCurrentNewEventScrollDirection = NewEventScrollDirection .NONE ;
96
102
private float mNewEventDragOffset = 0 ;
103
+ private Handler autoScrollHandler = new Handler (Looper .getMainLooper ());
104
+ private boolean isAutoScrolling = false ;
105
+ private Runnable autoScrollRunnable ;
106
+ private int mAutoScrollInterval = 1200 ;
107
+ private int mAutoScrollDuration = 300 ;
108
+ private int mAutoScrollLeftThreshold = 150 ;
109
+ private int mAutoScrollRightThreshold = 150 ;
97
110
98
111
// Attributes and their default values.
99
112
private int mHourHeight = 50 ;
@@ -299,7 +312,7 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float d
299
312
300
313
@ Override
301
314
public boolean onFling (MotionEvent e1 , MotionEvent e2 , float velocityX , float velocityY ) {
302
- if (mIsZooming )
315
+ if (mIsZooming || movingNewEvent )
303
316
return true ;
304
317
305
318
if ((mCurrentFlingDirection == Direction .LEFT && !mHorizontalFlingEnabled ) ||
@@ -2488,8 +2501,6 @@ public int getMinOverlappingMinutes() {
2488
2501
@ Override
2489
2502
public boolean onTouchEvent (MotionEvent event ) {
2490
2503
// TODO: fix single tap up
2491
- // TODO: fix horizontal auto scroll when dragging
2492
- // TODO: fix on drag verspringt bij start dragging -> lost op door verticale drag offset variabele toe te voegen
2493
2504
mScaleDetector .onTouchEvent (event );
2494
2505
boolean val = mGestureDetector .onTouchEvent (event );
2495
2506
if (event .getAction () == MotionEvent .ACTION_DOWN && creatingNewEvent && wasOnNewEventRect (event )) {
@@ -2500,7 +2511,11 @@ public boolean onTouchEvent(MotionEvent event) {
2500
2511
}
2501
2512
2502
2513
if (event .getAction () == MotionEvent .ACTION_UP && movingNewEvent ) {
2503
- stopScrolling ();
2514
+ if (isAutoScrolling ) {
2515
+ stopAutoScroll ();
2516
+ } else {
2517
+ stopScrolling ();
2518
+ }
2504
2519
movingNewEvent = false ;
2505
2520
}
2506
2521
@@ -2511,20 +2526,28 @@ public boolean onTouchEvent(MotionEvent event) {
2511
2526
float pixelsFromZero = event .getY () - mHeaderHeight
2512
2527
- mHeaderRowPadding * 2 - mTimeTextHeight / 2 - mHeaderMarginBottom ;
2513
2528
if (pixelsFromZero < mHourHeight ) {
2514
- if (mCurrentNewEventScrollDirection == NewEventScrollDirection .NONE ) {
2529
+ if (mCurrentNewEventScrollDirection == NewEventScrollDirection .NONE && ! isAutoScrolling ) {
2515
2530
mCurrentNewEventScrollDirection = NewEventScrollDirection .UP ;
2516
2531
int distance = (int ) getYMaxLimit () - (int ) mCurrentOrigin .y ;
2517
2532
mScroller .startScroll ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , 0 ,distance , Math .abs (distance / mHourHeight * mNewEventVerticalScrollDuration ));
2533
+ ViewCompat .postInvalidateOnAnimation (WeekView .this );
2518
2534
}
2519
2535
} else if (event .getY () > getHeight () - mHourHeight ) {
2520
- if (mCurrentNewEventScrollDirection == NewEventScrollDirection .NONE ) {
2536
+ if (mCurrentNewEventScrollDirection == NewEventScrollDirection .NONE && ! isAutoScrolling ) {
2521
2537
mCurrentNewEventScrollDirection = NewEventScrollDirection .DOWN ;
2522
2538
int distance = (int ) getYMinLimit () - (int ) mCurrentOrigin .y ;
2523
2539
mScroller .startScroll ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , 0 , distance , Math .abs (distance / mHourHeight * mNewEventVerticalScrollDuration ));
2540
+ ViewCompat .postInvalidateOnAnimation (WeekView .this );
2524
2541
}
2542
+ } else if (event .getX () < mAutoScrollLeftThreshold ) {
2543
+ if (!isAutoScrolling ) startAutoScroll (AutoScrollDirection .LEFT );
2544
+ } else if (getWidth () - event .getX () < mAutoScrollRightThreshold ) {
2545
+ if (!isAutoScrolling ) startAutoScroll (AutoScrollDirection .RIGHT );
2525
2546
} else if (mCurrentNewEventScrollDirection == NewEventScrollDirection .UP || mCurrentNewEventScrollDirection == NewEventScrollDirection .DOWN ) {
2526
2547
mCurrentNewEventScrollDirection = NewEventScrollDirection .NONE ;
2527
2548
mScroller .forceFinished (true );
2549
+ } else if (isAutoScrolling ) {
2550
+ stopAutoScroll ();
2528
2551
}
2529
2552
}
2530
2553
@@ -2539,6 +2562,42 @@ public boolean onTouchEvent(MotionEvent event) {
2539
2562
return val ;
2540
2563
}
2541
2564
2565
+ // Call this when user enters the critical area (left or right edge)
2566
+ private void startAutoScroll (AutoScrollDirection direction ) {
2567
+ if (isAutoScrolling || !mScroller .isFinished ()) return ;
2568
+
2569
+ isAutoScrolling = true ;
2570
+ autoScrollRunnable = new Runnable () {
2571
+ @ Override
2572
+ public void run () {
2573
+ scrollOneWeek (direction );
2574
+ autoScrollHandler .postDelayed (this , mAutoScrollInterval );
2575
+ }
2576
+ };
2577
+ autoScrollHandler .post (autoScrollRunnable );
2578
+ }
2579
+
2580
+ // Call this when user leaves the critical area
2581
+ private void stopAutoScroll () {
2582
+ isAutoScrolling = false ;
2583
+ if (autoScrollRunnable != null ) {
2584
+ autoScrollHandler .removeCallbacks (autoScrollRunnable );
2585
+ autoScrollRunnable = null ;
2586
+ }
2587
+ }
2588
+
2589
+ // Replace with your actual scroll logic
2590
+ private void scrollOneWeek (AutoScrollDirection direction ) {
2591
+ int distance = (int ) -(mNumberOfVisibleDays * (mWidthPerDay + mColumnGap ));
2592
+ if (direction == AutoScrollDirection .RIGHT ) {
2593
+ mScroller .startScroll ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y ,distance , 0 , mAutoScrollDuration );
2594
+ ViewCompat .postInvalidateOnAnimation (WeekView .this );
2595
+ } else if (direction == AutoScrollDirection .LEFT ) {
2596
+ mScroller .startScroll ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , -distance , 0 , mAutoScrollDuration );
2597
+ ViewCompat .postInvalidateOnAnimation (WeekView .this );
2598
+ }
2599
+ }
2600
+
2542
2601
/**
2543
2602
* A lighter function to stop the current scroll animation
2544
2603
*/
@@ -2617,12 +2676,7 @@ public void computeScroll() {
2617
2676
* @return true if scrolling should be stopped before reaching the end of animation.
2618
2677
*/
2619
2678
private boolean forceFinishScroll () {
2620
- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .ICE_CREAM_SANDWICH ) {
2621
- // current velocity only available since api 14
2622
- return mScroller .getCurrVelocity () <= mMinimumFlingVelocity ;
2623
- } else {
2624
- return false ;
2625
- }
2679
+ return mScroller .getCurrVelocity () <= mMinimumFlingVelocity ;
2626
2680
}
2627
2681
2628
2682
@@ -2726,9 +2780,15 @@ public boolean dateIsValid(Calendar day) {
2726
2780
2727
2781
private void updateNewEvent (MotionEvent e ) {
2728
2782
Log .d ("QuivrWeekView" , String .format ("updateNewEvent: %s%n" , e .toString ()));
2729
- Log .d ("QuivrWeekView" , String .format (Float .valueOf (mNewEventDragOffset ).toString ()));
2730
- Log .d ("QuivrWeekView" , String .format (Float .valueOf (e .getY ()).toString ()));
2731
- Calendar selectedTime = getTimeFromPoint (e .getX (), e .getY () - mNewEventDragOffset );
2783
+
2784
+ float x = e .getX ();
2785
+
2786
+ // Ugly fix for when the user is dragging the event over the small left time column
2787
+ if (x < mHeaderColumnWidth ) {
2788
+ x = mHeaderColumnWidth + 1 ;
2789
+ }
2790
+
2791
+ Calendar selectedTime = getTimeFromPoint (x , e .getY () - mNewEventDragOffset );
2732
2792
if (selectedTime != null ) {
2733
2793
List <WeekViewEvent > tempEvents = new ArrayList <>(mEvents );
2734
2794
if (mNewEventRect != null ) {
0 commit comments