Skip to content

Commit 8c93b27

Browse files
committed
fix: automatic horizontal scroll when dragging new event
1 parent de76570 commit 8c93b27

File tree

1 file changed

+75
-15
lines changed

1 file changed

+75
-15
lines changed

library/src/main/java/com/alamkanak/weekview/WeekView.java

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
import androidx.core.view.GestureDetectorCompat;
1212
import androidx.core.view.ViewCompat;
1313
import androidx.interpolator.view.animation.FastOutLinearInInterpolator;
14+
15+
import android.os.Handler;
16+
import android.os.Looper;
1417
import android.text.*;
1518
import android.text.format.DateFormat;
1619
import android.text.style.StyleSpan;
@@ -38,6 +41,9 @@ private enum Direction {
3841
private enum NewEventScrollDirection {
3942
NONE, UP, DOWN
4043
}
44+
private enum AutoScrollDirection {
45+
LEFT, RIGHT
46+
}
4147

4248
@Deprecated
4349
public static final int LENGTH_SHORT = 1;
@@ -94,6 +100,13 @@ private enum NewEventScrollDirection {
94100
private boolean movingNewEvent = false;
95101
private NewEventScrollDirection mCurrentNewEventScrollDirection = NewEventScrollDirection.NONE;
96102
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;
97110

98111
// Attributes and their default values.
99112
private int mHourHeight = 50;
@@ -299,7 +312,7 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float d
299312

300313
@Override
301314
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
302-
if (mIsZooming)
315+
if (mIsZooming || movingNewEvent)
303316
return true;
304317

305318
if ((mCurrentFlingDirection == Direction.LEFT && !mHorizontalFlingEnabled) ||
@@ -2488,8 +2501,6 @@ public int getMinOverlappingMinutes() {
24882501
@Override
24892502
public boolean onTouchEvent(MotionEvent event) {
24902503
// 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
24932504
mScaleDetector.onTouchEvent(event);
24942505
boolean val = mGestureDetector.onTouchEvent(event);
24952506
if (event.getAction() == MotionEvent.ACTION_DOWN && creatingNewEvent && wasOnNewEventRect(event)) {
@@ -2500,7 +2511,11 @@ public boolean onTouchEvent(MotionEvent event) {
25002511
}
25012512

25022513
if (event.getAction() == MotionEvent.ACTION_UP && movingNewEvent) {
2503-
stopScrolling();
2514+
if (isAutoScrolling) {
2515+
stopAutoScroll();
2516+
} else {
2517+
stopScrolling();
2518+
}
25042519
movingNewEvent = false;
25052520
}
25062521

@@ -2511,20 +2526,28 @@ public boolean onTouchEvent(MotionEvent event) {
25112526
float pixelsFromZero = event.getY() - mHeaderHeight
25122527
- mHeaderRowPadding * 2 - mTimeTextHeight / 2 - mHeaderMarginBottom;
25132528
if (pixelsFromZero < mHourHeight) {
2514-
if (mCurrentNewEventScrollDirection == NewEventScrollDirection.NONE) {
2529+
if (mCurrentNewEventScrollDirection == NewEventScrollDirection.NONE && !isAutoScrolling) {
25152530
mCurrentNewEventScrollDirection = NewEventScrollDirection.UP;
25162531
int distance = (int) getYMaxLimit() - (int) mCurrentOrigin.y;
25172532
mScroller.startScroll((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, 0,distance, Math.abs(distance / mHourHeight * mNewEventVerticalScrollDuration));
2533+
ViewCompat.postInvalidateOnAnimation(WeekView.this);
25182534
}
25192535
} else if (event.getY() > getHeight() - mHourHeight) {
2520-
if (mCurrentNewEventScrollDirection == NewEventScrollDirection.NONE) {
2536+
if (mCurrentNewEventScrollDirection == NewEventScrollDirection.NONE && !isAutoScrolling) {
25212537
mCurrentNewEventScrollDirection = NewEventScrollDirection.DOWN;
25222538
int distance = (int) getYMinLimit() - (int) mCurrentOrigin.y;
25232539
mScroller.startScroll((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, 0, distance, Math.abs(distance / mHourHeight * mNewEventVerticalScrollDuration));
2540+
ViewCompat.postInvalidateOnAnimation(WeekView.this);
25242541
}
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);
25252546
} else if (mCurrentNewEventScrollDirection == NewEventScrollDirection.UP || mCurrentNewEventScrollDirection == NewEventScrollDirection.DOWN) {
25262547
mCurrentNewEventScrollDirection = NewEventScrollDirection.NONE;
25272548
mScroller.forceFinished(true);
2549+
} else if (isAutoScrolling) {
2550+
stopAutoScroll();
25282551
}
25292552
}
25302553

@@ -2539,6 +2562,42 @@ public boolean onTouchEvent(MotionEvent event) {
25392562
return val;
25402563
}
25412564

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+
25422601
/**
25432602
* A lighter function to stop the current scroll animation
25442603
*/
@@ -2617,12 +2676,7 @@ public void computeScroll() {
26172676
* @return true if scrolling should be stopped before reaching the end of animation.
26182677
*/
26192678
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;
26262680
}
26272681

26282682

@@ -2726,9 +2780,15 @@ public boolean dateIsValid(Calendar day) {
27262780

27272781
private void updateNewEvent(MotionEvent e) {
27282782
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);
27322792
if (selectedTime != null) {
27332793
List<WeekViewEvent> tempEvents = new ArrayList<>(mEvents);
27342794
if (mNewEventRect != null) {

0 commit comments

Comments
 (0)