Skip to content

Commit 769f027

Browse files
author
Jens Claes
committed
Merge pull request #232 from marunjar/fix-scrolling
fix scroll issues
2 parents 3d8d98c + d183acd commit 769f027

File tree

1 file changed

+85
-23
lines changed

1 file changed

+85
-23
lines changed

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

Lines changed: 85 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
import android.graphics.RectF;
1111
import android.graphics.Region;
1212
import android.graphics.Typeface;
13+
import android.os.Build;
1314
import android.support.annotation.Nullable;
1415
import android.support.v4.view.GestureDetectorCompat;
1516
import android.support.v4.view.ViewCompat;
17+
import android.support.v4.view.animation.FastOutLinearInInterpolator;
1618
import android.text.Layout;
1719
import android.text.SpannableStringBuilder;
1820
import android.text.StaticLayout;
@@ -28,6 +30,7 @@
2830
import android.view.ScaleGestureDetector;
2931
import android.view.SoundEffectConstants;
3032
import android.view.View;
33+
import android.view.ViewConfiguration;
3134
import android.widget.OverScroller;
3235

3336
import java.text.SimpleDateFormat;
@@ -44,6 +47,10 @@
4447
*/
4548
public class WeekView extends View {
4649

50+
private enum Direction {
51+
NONE, LEFT, RIGHT, VERTICAL
52+
}
53+
4754
@Deprecated
4855
public static final int LENGTH_SHORT = 1;
4956
@Deprecated
@@ -86,7 +93,8 @@ public class WeekView extends View {
8693
private Calendar mFirstVisibleDay;
8794
private Calendar mLastVisibleDay;
8895
private int mDefaultEventColor;
89-
96+
private int mMinimumFlingVelocity = 0;
97+
private int mScaledTouchSlop = 0;
9098
// Attributes and their default values.
9199
private int mHourHeight = 50;
92100
private int mNewHourHeight = -1;
@@ -152,20 +160,40 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float d
152160
if (mIsZooming)
153161
return true;
154162

155-
// Calculate the direction to scroll.
156-
if (mCurrentScrollDirection == Direction.NONE) {
157-
// allow scrolling only in one direction
158-
if (Math.abs(distanceX) > Math.abs(distanceY)){
159-
mCurrentScrollDirection = Direction.HORIZONTAL;
163+
switch (mCurrentScrollDirection) {
164+
case NONE: {
165+
// allow scrolling only in one direction
166+
if (Math.abs(distanceX) > Math.abs(distanceY)) {
167+
if (distanceX > 0) {
168+
mCurrentScrollDirection = Direction.LEFT;
169+
} else {
170+
mCurrentScrollDirection = Direction.RIGHT;
171+
}
172+
} else {
173+
mCurrentScrollDirection = Direction.VERTICAL;
174+
}
175+
break;
160176
}
161-
else {
162-
mCurrentScrollDirection = Direction.VERTICAL;
177+
case LEFT: {
178+
// change direction if there was enough change
179+
if (Math.abs(distanceX) > Math.abs(distanceY) && (distanceX < -mScaledTouchSlop)) {
180+
mCurrentScrollDirection = Direction.RIGHT;
181+
}
182+
break;
183+
}
184+
case RIGHT: {
185+
// change direction if there was enough change
186+
if (Math.abs(distanceX) > Math.abs(distanceY) && (distanceX > mScaledTouchSlop)) {
187+
mCurrentScrollDirection = Direction.LEFT;
188+
}
189+
break;
163190
}
164191
}
165192

166193
// Calculate the new origin after scroll.
167194
switch (mCurrentScrollDirection) {
168-
case HORIZONTAL:
195+
case LEFT:
196+
case RIGHT:
169197
mCurrentOrigin.x -= distanceX * mXScrollingSpeed;
170198
ViewCompat.postInvalidateOnAnimation(WeekView.this);
171199
break;
@@ -179,14 +207,20 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float d
179207

180208
@Override
181209
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
210+
if (mIsZooming)
211+
return true;
212+
182213
mScroller.forceFinished(true);
183214

184215
mCurrentFlingDirection = mCurrentScrollDirection;
185-
if (mCurrentFlingDirection == Direction.HORIZONTAL){
186-
mScroller.fling((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, (int) (velocityX * mXScrollingSpeed), 0, Integer.MIN_VALUE, Integer.MAX_VALUE, (int) -(mHourHeight * 24 + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight/2 - getHeight()), 0);
187-
}
188-
else if (mCurrentFlingDirection == Direction.VERTICAL){
189-
mScroller.fling((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, 0, (int) velocityY, Integer.MIN_VALUE, Integer.MAX_VALUE, (int) -(mHourHeight * 24 + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight/2 - getHeight()), 0);
216+
switch (mCurrentFlingDirection) {
217+
case LEFT:
218+
case RIGHT:
219+
mScroller.fling((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, (int) (velocityX * mXScrollingSpeed), 0, Integer.MIN_VALUE, Integer.MAX_VALUE, (int) -(mHourHeight * 24 + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight / 2 - getHeight()), 0);
220+
break;
221+
case VERTICAL:
222+
mScroller.fling((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, 0, (int) velocityY, Integer.MIN_VALUE, Integer.MAX_VALUE, (int) -(mHourHeight * 24 + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight/2 - getHeight()), 0);
223+
break;
190224
}
191225

192226
ViewCompat.postInvalidateOnAnimation(WeekView.this);
@@ -248,10 +282,6 @@ public void onLongPress(MotionEvent e) {
248282
}
249283
};
250284

251-
private enum Direction {
252-
NONE, HORIZONTAL, VERTICAL
253-
}
254-
255285
public WeekView(Context context) {
256286
this(context, null);
257287
}
@@ -315,7 +345,10 @@ public WeekView(Context context, AttributeSet attrs, int defStyleAttr) {
315345
private void init() {
316346
// Scrolling initialization.
317347
mGestureDetector = new GestureDetectorCompat(mContext, mGestureListener);
318-
mScroller = new OverScroller(mContext);
348+
mScroller = new OverScroller(mContext, new FastOutLinearInInterpolator());
349+
350+
mMinimumFlingVelocity = ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity();
351+
mScaledTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
319352

320353
// Measure settings for time column.
321354
mTimeTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -1646,7 +1679,7 @@ public boolean onTouchEvent(MotionEvent event) {
16461679

16471680
// Check after call of mGestureDetector, so mCurrentFlingDirection and mCurrentScrollDirection are set.
16481681
if (event.getAction() == MotionEvent.ACTION_UP && !mIsZooming && mCurrentFlingDirection == Direction.NONE) {
1649-
if (mCurrentScrollDirection == Direction.HORIZONTAL) {
1682+
if (mCurrentScrollDirection == Direction.RIGHT || mCurrentScrollDirection == Direction.LEFT) {
16501683
goToNearestOrigin();
16511684
}
16521685
mCurrentScrollDirection = Direction.NONE;
@@ -1656,15 +1689,29 @@ public boolean onTouchEvent(MotionEvent event) {
16561689
}
16571690

16581691
private void goToNearestOrigin(){
1659-
float leftDays = Math.round(mCurrentOrigin.x / (mWidthPerDay + mColumnGap));
1692+
double leftDays = mCurrentOrigin.x / (mWidthPerDay + mColumnGap);
1693+
1694+
if (mCurrentFlingDirection != Direction.NONE) {
1695+
// snap to nearest day
1696+
leftDays = Math.round(leftDays);
1697+
} else if (mCurrentScrollDirection == Direction.LEFT) {
1698+
// snap to last day
1699+
leftDays = Math.floor(leftDays);
1700+
} else if (mCurrentScrollDirection == Direction.RIGHT) {
1701+
// snap to next day
1702+
leftDays = Math.ceil(leftDays);
1703+
} else {
1704+
// snap to nearest day
1705+
leftDays = Math.round(leftDays);
1706+
}
16601707

16611708
int nearestOrigin = (int) (mCurrentOrigin.x - leftDays * (mWidthPerDay + mColumnGap));
16621709

16631710
if (nearestOrigin != 0) {
16641711
// Stop current animation.
16651712
mScroller.forceFinished(true);
16661713
// Snap to date.
1667-
mScroller.startScroll((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, -nearestOrigin, 0, 50);
1714+
mScroller.startScroll((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, -nearestOrigin, 0, (int) (Math.abs(nearestOrigin) / mWidthPerDay * 500));
16681715
ViewCompat.postInvalidateOnAnimation(WeekView.this);
16691716
}
16701717
// Reset scrolling and fling direction.
@@ -1682,14 +1729,29 @@ public void computeScroll() {
16821729
goToNearestOrigin();
16831730
}
16841731
} else {
1685-
if (mScroller.computeScrollOffset()) {
1732+
if (mCurrentFlingDirection != Direction.NONE && forceFinishScroll()) {
1733+
goToNearestOrigin();
1734+
} else if (mScroller.computeScrollOffset()) {
16861735
mCurrentOrigin.y = mScroller.getCurrY();
16871736
mCurrentOrigin.x = mScroller.getCurrX();
16881737
ViewCompat.postInvalidateOnAnimation(this);
16891738
}
16901739
}
16911740
}
16921741

1742+
/**
1743+
* check if scrolling should be stopped
1744+
* @return true if scrolling should be stopped before reaching the end of animation
1745+
*/
1746+
private boolean forceFinishScroll() {
1747+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
1748+
// current velocity only available since api 14
1749+
return mScroller.getCurrVelocity() <= mMinimumFlingVelocity;
1750+
} else {
1751+
return false;
1752+
}
1753+
}
1754+
16931755

16941756
/////////////////////////////////////////////////////////////////
16951757
//

0 commit comments

Comments
 (0)