@@ -43,10 +43,12 @@ public class MonthListView extends ListView {
4343 private static int MULTIPLE_MONTH_VELOCITY_THRESHOLD = 2000 ;
4444 private static int FLING_VELOCITY_DIVIDER = 500 ;
4545 private static int FLING_TIME = 1000 ;
46+ private static int LEFT_RIGHT_DISTANCE = 150 ;
4647
4748 // disposable variable used for time calculations
4849 protected Time mTempTime ;
4950 private long mDownActionTime ;
51+ private float mLeftRightAction ;
5052 private final Rect mFirstViewRect = new Rect ();
5153
5254 Context mListContext ;
@@ -109,16 +111,29 @@ private boolean processEvent (MotionEvent ev) {
109111 case MotionEvent .ACTION_DOWN :
110112 mTracker .clear ();
111113 mDownActionTime = SystemClock .uptimeMillis ();
114+ mLeftRightAction = ev .getX ();
112115 break ;
113116 // Accumulate velocity and do a custom fling when above threshold
117+ // and look for left/right swipes as well.
114118 case MotionEvent .ACTION_UP :
119+ // Check for the fling.
115120 mTracker .addMovement (ev );
116121 mTracker .computeCurrentVelocity (1000 ); // in pixels per second
117122 float vel = mTracker .getYVelocity ();
118123 if (Math .abs (vel ) > MIN_VELOCITY_FOR_FLING ) {
119124 doFling (vel );
120125 return true ;
121126 }
127+ // Check for the left/right swipe.
128+ float leftRightSwipe = mLeftRightAction - ev .getX ();
129+ if ( Math .abs (leftRightSwipe ) > LEFT_RIGHT_DISTANCE ) {
130+ if ( leftRightSwipe > 0 ) {
131+ doLeftRight (1 );
132+ } else {
133+ doLeftRight (-1 );
134+ }
135+ return true ;
136+ }
122137 break ;
123138 default :
124139 mTracker .addMovement (ev );
@@ -185,6 +200,46 @@ private void doFling(float velocityY) {
185200 smoothScrollBy (viewsToFling * firstViewHeight + offset , FLING_TIME );
186201 }
187202
203+ // Do a "snap to start of month" fling
204+ // Left = +1
205+ // Right = -1
206+ private void doLeftRight (int monthsToJump ) {
207+
208+ // Stop the list-view movement and take over
209+ MotionEvent cancelEvent = MotionEvent .obtain (mDownActionTime , SystemClock .uptimeMillis (),
210+ MotionEvent .ACTION_CANCEL , 0 , 0 , 0 );
211+ onTouchEvent (cancelEvent );
212+
213+ // Get the day at the top right corner
214+ int day = getUpperRightJulianDay ();
215+ // Get the day of the first day of the next/previous month
216+ // (according to scroll direction) and make sure we're crossing
217+ // the boundry.
218+ mTempTime .setJulianDay (day + 6 );
219+ mTempTime .setDay (1 );
220+ mTempTime .setMonth (mTempTime .getMonth () + monthsToJump );
221+ long timeInMillis = mTempTime .normalize ();
222+ // Since each view is 7 days, round the target day up to make sure the
223+ // scroll will be at least one view.
224+ int scrollToDay = Time .getJulianDay (timeInMillis , mTempTime .getGmtOffset ())
225+ + ((monthsToJump > 0 ) ? 6 : 0 );
226+
227+ // Since all views have the same height, scroll by pixels instead of
228+ // "to position".
229+ // Compensate for the top view offset from the top.
230+ View firstView = getChildAt (0 );
231+ int firstViewHeight = firstView .getHeight ();
232+ // Get visible part length
233+ firstView .getLocalVisibleRect (mFirstViewRect );
234+ int topViewVisiblePart = mFirstViewRect .bottom - mFirstViewRect .top ;
235+ int viewsToFling = (scrollToDay - day ) / 7 - ((monthsToJump <= 0 ) ? 1 : 0 );
236+ int offset = (viewsToFling > 0 ) ? -(firstViewHeight - topViewVisiblePart
237+ + SimpleDayPickerFragment .LIST_TOP_OFFSET ) : (topViewVisiblePart
238+ - SimpleDayPickerFragment .LIST_TOP_OFFSET );
239+ // Fling
240+ smoothScrollBy (viewsToFling * firstViewHeight + offset , FLING_TIME );
241+ }
242+
188243 // Returns the julian day of the day in the upper right corner
189244 private int getUpperRightJulianDay () {
190245 SimpleWeekView child = (SimpleWeekView ) getChildAt (0 );
0 commit comments