11package com .henninghall .date_picker ;
22
3+ import android .annotation .SuppressLint ;
34import android .view .View ;
45import android .widget .RelativeLayout ;
56
67import com .facebook .react .bridge .Arguments ;
78import com .facebook .react .bridge .WritableMap ;
89import com .facebook .react .uimanager .events .RCTEventEmitter ;
10+ import com .henninghall .date_picker .wheelFunctions .AnimateToDate ;
11+ import com .henninghall .date_picker .wheelFunctions .Refresh ;
12+ import com .henninghall .date_picker .wheelFunctions .SetDate ;
13+ import com .henninghall .date_picker .wheelFunctions .WheelFunction ;
914import com .henninghall .date_picker .wheels .AmPmWheel ;
1015import com .henninghall .date_picker .wheels .DayWheel ;
1116import com .henninghall .date_picker .wheels .HourWheel ;
1621
1722import java .text .ParseException ;
1823import java .text .SimpleDateFormat ;
24+ import java .util .ArrayList ;
25+ import java .util .Arrays ;
1926import java .util .Calendar ;
27+ import java .util .Collection ;
2028import java .util .Date ;
29+ import java .util .List ;
2130import java .util .Locale ;
2231
2332import cn .carbswang .android .numberpickerview .library .NumberPickerView ;
2433
2534
2635public class PickerView extends RelativeLayout {
2736
28- private final RelativeLayout wheelsWrapper ;
2937 private final NumberPickerView hourPicker ;
3038 private final NumberPickerView ampmPicker ;
3139 private SimpleDateFormat dateFormat ;
3240 private HourWheel hourWheel ;
3341 private DayWheel dayWheel ;
34- private MinutesWheel minutesWheel ;
42+ public MinutesWheel minutesWheel ;
3543 private AmPmWheel ampmWheel ;
3644 private Date minDate ;
3745 private Date maxDate ;
46+ public int minuteInterval = 1 ;
47+ public Locale locale ;
3848
3949 public PickerView () {
4050 super (DatePickerManager .context );
4151 View rootView = inflate (getContext (), R .layout .datepicker_view , this );
4252
43- wheelsWrapper = (RelativeLayout ) rootView .findViewById (R .id .wheelsWrapper );
53+ RelativeLayout wheelsWrapper = (RelativeLayout ) rootView .findViewById (R .id .wheelsWrapper );
4454 wheelsWrapper .setWillNotDraw (false );
4555
46- Locale locale = android .os .Build .VERSION .SDK_INT >= android .os .Build .VERSION_CODES .LOLLIPOP ? Locale .forLanguageTag ("en" ) : Locale .getDefault ();
56+ locale = android .os .Build .VERSION .SDK_INT >= android .os .Build .VERSION_CODES .LOLLIPOP ? Locale .forLanguageTag ("en" ) : Locale .getDefault ();
4757
4858 NumberPickerView dayPicker = (NumberPickerView ) rootView .findViewById (R .id .day );
49- dayWheel = new DayWheel (dayPicker , onWheelChangeListener , locale );
59+ dayWheel = new DayWheel (dayPicker , this );
5060
5161 NumberPickerView minutePicker = (NumberPickerView ) rootView .findViewById (R .id .minutes );
52- minutesWheel = new MinutesWheel (minutePicker , onWheelChangeListener , locale );
62+ minutesWheel = new MinutesWheel (minutePicker , this );
5363
5464 ampmPicker = (NumberPickerView ) rootView .findViewById (R .id .ampm );
55- ampmWheel = new AmPmWheel (ampmPicker , onWheelChangeListener , locale );
65+ ampmWheel = new AmPmWheel (ampmPicker , this );
5666
5767 hourPicker = (NumberPickerView ) rootView .findViewById (R .id .hour );
58- hourWheel = new HourWheel (hourPicker , onWheelChangeListener , locale );
68+ hourWheel = new HourWheel (hourPicker ,this );
5969
6070 dateFormat = new SimpleDateFormat (getDateFormatTemplate (), Locale .US );
6171 changeAmPmWhenPassingMidnightOrNoon ();
62-
6372 }
6473
6574 WheelChangeListener onWheelChangeListener = new WheelChangeListener (){
@@ -68,8 +77,8 @@ public void onChange(Wheel wheel) {
6877 WritableMap event = Arguments .createMap ();
6978 try {
7079 Date date = dateFormat .parse (getDateString ());
71- if (date .before (minDate )) wheel . animateToDate ( minDate );
72- if (date .after (maxDate )) wheel . animateToDate ( maxDate );
80+ if (date .before (minDate )) applyOnVisibleWheels ( new AnimateToDate ( minDate ) );
81+ if (date .after (maxDate )) applyOnVisibleWheels ( new AnimateToDate ( maxDate ) );
7382 else {
7483 event .putDouble ("date" , date .getTime ());
7584 DatePickerManager .context .getJSModule (RCTEventEmitter .class ).receiveEvent (getId (), "dateChange" , event );
@@ -80,12 +89,72 @@ public void onChange(Wheel wheel) {
8089 }
8190 };
8291
92+ private final Runnable measureAndLayout = new Runnable () {
93+ @ Override
94+ public void run () {
95+ measure (
96+ MeasureSpec .makeMeasureSpec (getWidth (), MeasureSpec .EXACTLY ),
97+ MeasureSpec .makeMeasureSpec (getHeight (), MeasureSpec .EXACTLY ));
98+ layout (getLeft (), getTop (), getRight (), getBottom ());
99+ }
100+ };
101+
102+ private void changeAmPmWhenPassingMidnightOrNoon (){
103+ hourPicker .setOnValueChangeListenerInScrolling (new NumberPickerView .OnValueChangeListenerInScrolling () {
104+ @ Override
105+ public void onValueChangeInScrolling (NumberPickerView picker , int oldVal , int newVal ) {
106+ if (Utils .usesAmPm (locale )){
107+ String oldValue = hourWheel .getValueAtIndex (oldVal );
108+ String newValue = hourWheel .getValueAtIndex (newVal );
109+ boolean passingNoonOrMidnight = (oldValue .equals ("12" ) && newValue .equals ("11" )) || oldValue .equals ("11" ) && newValue .equals ("12" );
110+ if (passingNoonOrMidnight ) ampmPicker .smoothScrollToValue ((ampmPicker .getValue () + 1 ) % 2 ,false );
111+ }
112+ }
113+ });
114+ }
115+
116+ public void setMinimumDate (Date date ) {
117+ minDate = DateUtils .truncate (date , Calendar .MINUTE );
118+ }
119+
120+ public void setMaximumDate (Date date ) {
121+ maxDate = DateUtils .truncate (date , Calendar .MINUTE );
122+ }
123+
124+ public void setDate (Date date ) {
125+ applyOnVisibleWheels (new SetDate (date ));
126+ }
127+
128+ public void setLocale (Locale locale ) {
129+ this .locale = locale ;
130+ dateFormat = new SimpleDateFormat (getDateFormatTemplate (), Locale .US );
131+ applyOnAllWheels (new Refresh ());
132+ }
133+
134+ public void setMinuteInterval (int interval ) {
135+ this .minuteInterval = interval ;
136+ applyOnVisibleWheels (new Refresh ());
137+ }
138+
139+ // Rounding cal to closest minute interval
140+ public Calendar getInitialDate () {
141+ Calendar cal = Calendar .getInstance ();
142+ if (minuteInterval <= 1 ) return cal ;
143+ int exactMinute = Integer .valueOf (minutesWheel .format .format (cal .getTime ()));
144+ int diffSinceLastInterval = exactMinute % minuteInterval ;
145+ int diffAhead = minuteInterval - diffSinceLastInterval ;
146+ int diffBehind = -diffSinceLastInterval ;
147+ boolean closerToPrevious = minuteInterval / 2 > diffSinceLastInterval ;
148+ int diffToExactValue = closerToPrevious ? diffBehind : diffAhead ;
149+ cal .add (Calendar .MINUTE , diffToExactValue );
150+ return (Calendar ) cal .clone ();
151+ }
83152
84153 private String getDateFormatTemplate () {
85154 return dayWheel .getFormatTemplate () + " "
86155 + hourWheel .getFormatTemplate () + " "
87156 + minutesWheel .getFormatTemplate ()
88- + ampmWheel .getFormatTemplate ();
157+ + ampmWheel .getFormatTemplate ();
89158 }
90159
91160 private String getDateString () {
@@ -95,58 +164,36 @@ private String getDateString() {
95164 + ampmWheel .getValue ();
96165 }
97166
98- public void setMinimumDate (Date date ) {
99- minDate = DateUtils .truncate (date , Calendar .MINUTE );
167+ public Collection <Wheel > getVisibleWheels () {
168+ Collection <Wheel > visibleWheels = new ArrayList <>();
169+ for (Wheel wheel : getAllWheels ()) {
170+ if (wheel .visible ()) {
171+ visibleWheels .add (wheel );
172+ }
173+ }
174+ return visibleWheels ;
100175 }
101176
102- public void setMaximumDate ( Date date ) {
103- maxDate = DateUtils . truncate ( date , Calendar . MINUTE );
177+ public List < Wheel > getAllWheels () {
178+ return new ArrayList <>( Arrays . asList ( dayWheel , hourWheel , minutesWheel , ampmWheel ) );
104179 }
105180
106- public void setDate (Date date ) {
107- dayWheel .setValue (date );
108- hourWheel .setValue (date );
109- minutesWheel .setValue (date );
110- ampmWheel .setValue (date );
181+ public void applyOnAllWheels (WheelFunction function ) {
182+ for (Wheel wheel : getAllWheels ()) function .apply (wheel );
111183 }
112184
113- public void setLocale (Locale locale ) {
114- dayWheel .setLocale (locale );
115- hourWheel .setLocale (locale );
116- minutesWheel .setLocale (locale );
117- ampmWheel .setLocale (locale );
118-
119- dateFormat = new SimpleDateFormat (getDateFormatTemplate (), Locale .US );
185+ public void applyOnVisibleWheels (WheelFunction function ) {
186+ for (Wheel wheel : getVisibleWheels ()) function .apply (wheel );
120187 }
121188
122- private final Runnable measureAndLayout = new Runnable () {
123- @ Override
124- public void run () {
125- measure (
126- MeasureSpec .makeMeasureSpec (getWidth (), MeasureSpec .EXACTLY ),
127- MeasureSpec .makeMeasureSpec (getHeight (), MeasureSpec .EXACTLY ));
128- layout (getLeft (), getTop (), getRight (), getBottom ());
129- }
130- };
131-
132189 @ Override
133190 public void requestLayout () {
134191 super .requestLayout ();
135192 post (measureAndLayout );
136193 }
137194
138- private void changeAmPmWhenPassingMidnightOrNoon (){
139- hourPicker .setOnValueChangeListenerInScrolling (new NumberPickerView .OnValueChangeListenerInScrolling () {
140- @ Override
141- public void onValueChangeInScrolling (NumberPickerView picker , int oldVal , int newVal ) {
142- if (Utils .usesAmPm (hourWheel .getLocale ())){
143- String oldValue = hourWheel .getValueAtIndex (oldVal );
144- String newValue = hourWheel .getValueAtIndex (newVal );
145- boolean passingNoonOrMidnight = (oldValue .equals ("12" ) && newValue .equals ("11" )) || oldValue .equals ("11" ) && newValue .equals ("12" );
146- if (passingNoonOrMidnight ) ampmPicker .smoothScrollToValue ((ampmPicker .getValue () + 1 ) % 2 );
147- }
148- }
149- });
150-
195+ public WheelChangeListener getListener () {
196+ return onWheelChangeListener ;
151197 }
198+
152199}
0 commit comments