@@ -110,6 +110,11 @@ private enum Direction {
110110 private int mScaledTouchSlop = 0 ;
111111 private EventRect mNewEventRect ;
112112 private TextColorPicker textColorPicker ;
113+ private float mSizeOfWeekView ;
114+ private float mDistanceDone = 0 ;
115+ private float mDistanceMin ;
116+ protected int mOffsetValueToSecureScreen = 9 ;
117+ private float mStartOriginForScroll = 0 ;
113118
114119 // Attributes and their default values.
115120 private int mHourHeight = 50 ;
@@ -118,7 +123,7 @@ private enum Direction {
118123 private int mEffectiveMinHourHeight = mMinHourHeight ; //compensates for the fact that you can't keep zooming out.
119124 private int mMaxHourHeight = 250 ;
120125 private int mColumnGap = 10 ;
121- private int mFirstDayOfWeek = Calendar .MONDAY ;
126+ private int mFirstDayOfWeek = Calendar .getInstance (). getFirstDayOfWeek () ;
122127 private int mTextSize = 12 ;
123128 private int mHeaderColumnPadding = 10 ;
124129 private int mHeaderColumnTextColor = Color .BLACK ;
@@ -174,6 +179,7 @@ private enum Direction {
174179 private boolean mAutoLimitTime = false ;
175180 private boolean mEnableDropListener = false ;
176181 private int mMinOverlappingMinutes = 0 ;
182+ private boolean mIsScrollNumberOfVisibleDays = false ;
177183
178184 // Listeners.
179185 private EventClickListener mEventClickListener ;
@@ -190,6 +196,7 @@ private enum Direction {
190196
191197 @ Override
192198 public boolean onDown (MotionEvent e ) {
199+ mStartOriginForScroll = mCurrentOrigin .x ;
193200 goToNearestOrigin ();
194201 return true ;
195202 }
@@ -238,6 +245,13 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float d
238245 case RIGHT :
239246 float minX = getXMinLimit ();
240247 float maxX = getXMaxLimit ();
248+
249+ if (e2 .getX () < 0 ) {
250+ mDistanceDone = e2 .getX () - e1 .getX ();
251+ } else {
252+ mDistanceDone = e1 .getX () - e2 .getX ();
253+ }
254+
241255 if ((mCurrentOrigin .x - (distanceX * mXScrollingSpeed )) > maxX ) {
242256 mCurrentOrigin .x = maxX ;
243257 } else if ((mCurrentOrigin .x - (distanceX * mXScrollingSpeed )) < minX ) {
@@ -282,7 +296,9 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve
282296 switch (mCurrentFlingDirection ) {
283297 case LEFT :
284298 case RIGHT :
285- mScroller .fling ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , (int ) (velocityX * mXScrollingSpeed ), 0 , (int ) getXMinLimit (), (int ) getXMaxLimit (), (int ) getYMinLimit (), (int ) getYMaxLimit ());
299+ if (!mIsScrollNumberOfVisibleDays ) {
300+ mScroller .fling ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , (int ) (velocityX * mXScrollingSpeed ), 0 , (int ) getXMinLimit (), (int ) getXMaxLimit (), (int ) getYMinLimit (), (int ) getYMaxLimit ());
301+ }
286302 break ;
287303 case VERTICAL :
288304 mScroller .fling ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , 0 , (int ) velocityY , (int ) getXMinLimit (), (int ) getXMaxLimit (), (int ) getYMinLimit (), (int ) getYMaxLimit ());
@@ -494,6 +510,7 @@ public WeekView(Context context, AttributeSet attrs, int defStyleAttr) {
494510 if (a .getBoolean (R .styleable .WeekView_dropListenerEnabled , false ))
495511 this .enableDropListener ();
496512 mMinOverlappingMinutes = a .getInt (R .styleable .WeekView_minOverlappingMinutes , 0 );
513+ mIsScrollNumberOfVisibleDays = a .getBoolean (R .styleable .WeekView_isScrollNumberOfVisibleDays , false );
497514 } finally {
498515 a .recycle ();
499516 }
@@ -2517,6 +2534,15 @@ public int getMinOverlappingMinutes() {
25172534 return this .mMinOverlappingMinutes ;
25182535 }
25192536
2537+ public boolean isScrollNumberOfVisibleDays () {
2538+ return this .mIsScrollNumberOfVisibleDays ;
2539+ }
2540+
2541+ public void setScrollNumberOfVisibleDays (boolean scrollNumberOfVisibleDays ) {
2542+ this .mIsScrollNumberOfVisibleDays = scrollNumberOfVisibleDays ;
2543+ invalidate ();
2544+ }
2545+
25202546 /////////////////////////////////////////////////////////////////
25212547 //
25222548 // Functions related to scrolling.
@@ -2525,6 +2551,10 @@ public int getMinOverlappingMinutes() {
25252551
25262552 @ Override
25272553 public boolean onTouchEvent (MotionEvent event ) {
2554+
2555+ mSizeOfWeekView = (mWidthPerDay + mColumnGap ) * getNumberOfVisibleDays ();
2556+ mDistanceMin = mSizeOfWeekView / mOffsetValueToSecureScreen ;
2557+
25282558 mScaleDetector .onTouchEvent (event );
25292559 boolean val = mGestureDetector .onTouchEvent (event );
25302560
@@ -2542,41 +2572,78 @@ public boolean onTouchEvent(MotionEvent event) {
25422572 private void goToNearestOrigin () {
25432573 double leftDays = mCurrentOrigin .x / (mWidthPerDay + mColumnGap );
25442574
2545- if (mCurrentFlingDirection != Direction .NONE ) {
2546- // snap to nearest day
2547- leftDays = Math .round (leftDays );
2548- } else if (mCurrentScrollDirection == Direction .LEFT ) {
2549- // snap to last day
2550- leftDays = Math .floor (leftDays );
2551- } else if (mCurrentScrollDirection == Direction .RIGHT ) {
2552- // snap to next day
2553- leftDays = Math .ceil (leftDays );
2554- } else {
2555- // snap to nearest day
2556- leftDays = Math .round (leftDays );
2557- }
2575+ float beforeScroll = mStartOriginForScroll ;
2576+ boolean isPassed = false ;
2577+
2578+ if (mDistanceDone > mDistanceMin || mDistanceDone < -mDistanceMin || !mIsScrollNumberOfVisibleDays ) {
2579+
2580+ if (!mIsScrollNumberOfVisibleDays && mCurrentFlingDirection != Direction .NONE ) {
2581+ // snap to nearest day
2582+ leftDays = Math .round (leftDays );
2583+ } else if (mCurrentScrollDirection == Direction .LEFT ) {
2584+ // snap to last day
2585+ leftDays = Math .floor (leftDays );
2586+ mStartOriginForScroll -= mSizeOfWeekView ;
2587+ isPassed = true ;
2588+ } else if (mCurrentScrollDirection == Direction .RIGHT ) {
2589+ // snap to next day
2590+ leftDays = Math .floor (leftDays );
2591+ mStartOriginForScroll += mSizeOfWeekView ;
2592+ isPassed = true ;
2593+ } else {
2594+ // snap to nearest day
2595+ leftDays = Math .round (leftDays );
2596+ }
25582597
2559- int nearestOrigin = (int ) (mCurrentOrigin .x - leftDays * (mWidthPerDay + mColumnGap ));
2560- boolean mayScrollHorizontal = mCurrentOrigin .x - nearestOrigin < getXMaxLimit ()
2561- && mCurrentOrigin .x - nearestOrigin > getXMinLimit ();
25622598
2563- if (mayScrollHorizontal ) {
2564- mScroller .startScroll ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , -nearestOrigin , 0 );
2565- ViewCompat .postInvalidateOnAnimation (WeekView .this );
2566- }
2599+ if (mIsScrollNumberOfVisibleDays ) {
2600+ boolean mayScrollHorizontal = beforeScroll - mStartOriginForScroll < getXMaxLimit () && mCurrentOrigin .x - mStartOriginForScroll > getXMinLimit ();
2601+ if (isPassed && mayScrollHorizontal ) {
2602+ // Stop current animation.
2603+ mScroller .forceFinished (true );
2604+ // Snap to date.
2605+ if (mCurrentScrollDirection == Direction .LEFT ) {
2606+ mScroller .startScroll ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , (int ) ((beforeScroll - mCurrentOrigin .x ) - mSizeOfWeekView ), 0 , 200 );
2607+ } else if (mCurrentScrollDirection == Direction .RIGHT ) {
2608+ mScroller .startScroll ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , (int ) (mSizeOfWeekView - (mCurrentOrigin .x - beforeScroll )), 0 , 200 );
2609+ }
2610+ ViewCompat .postInvalidateOnAnimation (WeekView .this );
2611+ }
2612+ } else {
2613+ int nearestOrigin = (int ) (mCurrentOrigin .x - leftDays * (mWidthPerDay + mColumnGap ));
2614+ boolean mayScrollHorizontal = mCurrentOrigin .x - nearestOrigin < getXMaxLimit () && mCurrentOrigin .x - nearestOrigin > getXMinLimit ();
2615+ if (mayScrollHorizontal ) {
2616+ mScroller .startScroll ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , -nearestOrigin , 0 );
2617+ ViewCompat .postInvalidateOnAnimation (WeekView .this );
2618+ }
25672619
2568- if (nearestOrigin != 0 && mayScrollHorizontal ) {
2569- // Stop current animation.
2620+ if (nearestOrigin != 0 && mayScrollHorizontal ) {
2621+ // Stop current animation.
2622+ mScroller .forceFinished (true );
2623+ // Snap to date.
2624+ mScroller .startScroll ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , -nearestOrigin , 0 , (int ) (Math .abs (nearestOrigin ) / mWidthPerDay * mScrollDuration ));
2625+ ViewCompat .postInvalidateOnAnimation (WeekView .this );
2626+ }
2627+ }
2628+
2629+ // Reset scrolling and fling direction.
2630+ mCurrentScrollDirection = mCurrentFlingDirection = Direction .NONE ;
2631+
2632+
2633+ } else {
25702634 mScroller .forceFinished (true );
2571- // Snap to date.
2572- mScroller .startScroll ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , -nearestOrigin , 0 , (int ) (Math .abs (nearestOrigin ) / mWidthPerDay * mScrollDuration ));
2635+ if (mCurrentScrollDirection == Direction .LEFT ) {
2636+ mScroller .startScroll ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , (int ) beforeScroll - (int ) mCurrentOrigin .x , 0 , 200 );
2637+ } else if (mCurrentScrollDirection == Direction .RIGHT ) {
2638+ mScroller .startScroll ((int ) mCurrentOrigin .x , (int ) mCurrentOrigin .y , (int ) beforeScroll - (int ) mCurrentOrigin .x , 0 , 200 );
2639+ }
25732640 ViewCompat .postInvalidateOnAnimation (WeekView .this );
2641+
2642+ // Reset scrolling and fling direction.
2643+ mCurrentScrollDirection = mCurrentFlingDirection = Direction .NONE ;
25742644 }
2575- // Reset scrolling and fling direction.
2576- mCurrentScrollDirection = mCurrentFlingDirection = Direction .NONE ;
25772645 }
25782646
2579-
25802647 @ Override
25812648 public void computeScroll () {
25822649 super .computeScroll ();
0 commit comments