|
@ -1,11 +1,16 @@ |
|
|
package com.henninghall.date_picker; |
|
|
package com.henninghall.date_picker; |
|
|
|
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint; |
|
|
import android.view.View; |
|
|
import android.view.View; |
|
|
import android.widget.RelativeLayout; |
|
|
import android.widget.RelativeLayout; |
|
|
|
|
|
|
|
|
import com.facebook.react.bridge.Arguments; |
|
|
import com.facebook.react.bridge.Arguments; |
|
|
import com.facebook.react.bridge.WritableMap; |
|
|
import com.facebook.react.bridge.WritableMap; |
|
|
import com.facebook.react.uimanager.events.RCTEventEmitter; |
|
|
import com.facebook.react.uimanager.events.RCTEventEmitter; |
|
|
|
|
|
import com.henninghall.date_picker.wheelFunctions.AnimateToDate; |
|
|
|
|
|
import com.henninghall.date_picker.wheelFunctions.Refresh; |
|
|
|
|
|
import com.henninghall.date_picker.wheelFunctions.SetDate; |
|
|
|
|
|
import com.henninghall.date_picker.wheelFunctions.WheelFunction; |
|
|
import com.henninghall.date_picker.wheels.AmPmWheel; |
|
|
import com.henninghall.date_picker.wheels.AmPmWheel; |
|
|
import com.henninghall.date_picker.wheels.DayWheel; |
|
|
import com.henninghall.date_picker.wheels.DayWheel; |
|
|
import com.henninghall.date_picker.wheels.HourWheel; |
|
|
import com.henninghall.date_picker.wheels.HourWheel; |
|
@ -16,8 +21,12 @@ import org.apache.commons.lang3.time.DateUtils; |
|
|
|
|
|
|
|
|
import java.text.ParseException; |
|
|
import java.text.ParseException; |
|
|
import java.text.SimpleDateFormat; |
|
|
import java.text.SimpleDateFormat; |
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
|
import java.util.Arrays; |
|
|
import java.util.Calendar; |
|
|
import java.util.Calendar; |
|
|
|
|
|
import java.util.Collection; |
|
|
import java.util.Date; |
|
|
import java.util.Date; |
|
|
|
|
|
import java.util.List; |
|
|
import java.util.Locale; |
|
|
import java.util.Locale; |
|
|
|
|
|
|
|
|
import cn.carbswang.android.numberpickerview.library.NumberPickerView; |
|
|
import cn.carbswang.android.numberpickerview.library.NumberPickerView; |
|
@ -25,41 +34,41 @@ import cn.carbswang.android.numberpickerview.library.NumberPickerView; |
|
|
|
|
|
|
|
|
public class PickerView extends RelativeLayout { |
|
|
public class PickerView extends RelativeLayout { |
|
|
|
|
|
|
|
|
private final RelativeLayout wheelsWrapper; |
|
|
|
|
|
private final NumberPickerView hourPicker; |
|
|
private final NumberPickerView hourPicker; |
|
|
private final NumberPickerView ampmPicker; |
|
|
private final NumberPickerView ampmPicker; |
|
|
private SimpleDateFormat dateFormat; |
|
|
private SimpleDateFormat dateFormat; |
|
|
private HourWheel hourWheel; |
|
|
private HourWheel hourWheel; |
|
|
private DayWheel dayWheel; |
|
|
private DayWheel dayWheel; |
|
|
private MinutesWheel minutesWheel; |
|
|
|
|
|
|
|
|
public MinutesWheel minutesWheel; |
|
|
private AmPmWheel ampmWheel; |
|
|
private AmPmWheel ampmWheel; |
|
|
private Date minDate; |
|
|
private Date minDate; |
|
|
private Date maxDate; |
|
|
private Date maxDate; |
|
|
|
|
|
public int minuteInterval = 1; |
|
|
|
|
|
public Locale locale; |
|
|
|
|
|
|
|
|
public PickerView() { |
|
|
public PickerView() { |
|
|
super(DatePickerManager.context); |
|
|
super(DatePickerManager.context); |
|
|
View rootView = inflate(getContext(), R.layout.datepicker_view, this); |
|
|
View rootView = inflate(getContext(), R.layout.datepicker_view, this); |
|
|
|
|
|
|
|
|
wheelsWrapper = (RelativeLayout) rootView.findViewById(R.id.wheelsWrapper); |
|
|
|
|
|
|
|
|
RelativeLayout wheelsWrapper = (RelativeLayout) rootView.findViewById(R.id.wheelsWrapper); |
|
|
wheelsWrapper.setWillNotDraw(false); |
|
|
wheelsWrapper.setWillNotDraw(false); |
|
|
|
|
|
|
|
|
Locale locale = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP ? Locale.forLanguageTag("en") : Locale.getDefault(); |
|
|
|
|
|
|
|
|
locale = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP ? Locale.forLanguageTag("en") : Locale.getDefault(); |
|
|
|
|
|
|
|
|
NumberPickerView dayPicker = (NumberPickerView) rootView.findViewById(R.id.day); |
|
|
NumberPickerView dayPicker = (NumberPickerView) rootView.findViewById(R.id.day); |
|
|
dayWheel = new DayWheel(dayPicker, onWheelChangeListener, locale); |
|
|
|
|
|
|
|
|
dayWheel = new DayWheel(dayPicker, this); |
|
|
|
|
|
|
|
|
NumberPickerView minutePicker = (NumberPickerView) rootView.findViewById(R.id.minutes); |
|
|
NumberPickerView minutePicker = (NumberPickerView) rootView.findViewById(R.id.minutes); |
|
|
minutesWheel = new MinutesWheel(minutePicker, onWheelChangeListener, locale); |
|
|
|
|
|
|
|
|
minutesWheel = new MinutesWheel(minutePicker, this); |
|
|
|
|
|
|
|
|
ampmPicker = (NumberPickerView) rootView.findViewById(R.id.ampm); |
|
|
ampmPicker = (NumberPickerView) rootView.findViewById(R.id.ampm); |
|
|
ampmWheel = new AmPmWheel(ampmPicker, onWheelChangeListener, locale); |
|
|
|
|
|
|
|
|
ampmWheel = new AmPmWheel(ampmPicker, this); |
|
|
|
|
|
|
|
|
hourPicker = (NumberPickerView) rootView.findViewById(R.id.hour); |
|
|
hourPicker = (NumberPickerView) rootView.findViewById(R.id.hour); |
|
|
hourWheel = new HourWheel(hourPicker, onWheelChangeListener, locale); |
|
|
|
|
|
|
|
|
hourWheel = new HourWheel(hourPicker,this); |
|
|
|
|
|
|
|
|
dateFormat = new SimpleDateFormat(getDateFormatTemplate(), Locale.US); |
|
|
dateFormat = new SimpleDateFormat(getDateFormatTemplate(), Locale.US); |
|
|
changeAmPmWhenPassingMidnightOrNoon(); |
|
|
changeAmPmWhenPassingMidnightOrNoon(); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
WheelChangeListener onWheelChangeListener = new WheelChangeListener(){ |
|
|
WheelChangeListener onWheelChangeListener = new WheelChangeListener(){ |
|
@ -68,8 +77,8 @@ public class PickerView extends RelativeLayout { |
|
|
WritableMap event = Arguments.createMap(); |
|
|
WritableMap event = Arguments.createMap(); |
|
|
try { |
|
|
try { |
|
|
Date date = dateFormat.parse(getDateString()); |
|
|
Date date = dateFormat.parse(getDateString()); |
|
|
if (date.before(minDate)) wheel.animateToDate(minDate); |
|
|
|
|
|
if (date.after(maxDate)) wheel.animateToDate(maxDate); |
|
|
|
|
|
|
|
|
if (date.before(minDate)) applyOnVisibleWheels(new AnimateToDate(minDate)); |
|
|
|
|
|
if (date.after(maxDate)) applyOnVisibleWheels(new AnimateToDate(maxDate)); |
|
|
else { |
|
|
else { |
|
|
event.putDouble("date", date.getTime()); |
|
|
event.putDouble("date", date.getTime()); |
|
|
DatePickerManager.context.getJSModule(RCTEventEmitter.class).receiveEvent(getId(), "dateChange", event); |
|
|
DatePickerManager.context.getJSModule(RCTEventEmitter.class).receiveEvent(getId(), "dateChange", event); |
|
@ -80,12 +89,72 @@ public class PickerView extends RelativeLayout { |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
private final Runnable measureAndLayout = new Runnable() { |
|
|
|
|
|
@Override |
|
|
|
|
|
public void run() { |
|
|
|
|
|
measure( |
|
|
|
|
|
MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY), |
|
|
|
|
|
MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY)); |
|
|
|
|
|
layout(getLeft(), getTop(), getRight(), getBottom()); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
private void changeAmPmWhenPassingMidnightOrNoon(){ |
|
|
|
|
|
hourPicker.setOnValueChangeListenerInScrolling(new NumberPickerView.OnValueChangeListenerInScrolling() { |
|
|
|
|
|
@Override |
|
|
|
|
|
public void onValueChangeInScrolling(NumberPickerView picker, int oldVal, int newVal) { |
|
|
|
|
|
if(Utils.usesAmPm(locale)){ |
|
|
|
|
|
String oldValue = hourWheel.getValueAtIndex(oldVal); |
|
|
|
|
|
String newValue = hourWheel.getValueAtIndex(newVal); |
|
|
|
|
|
boolean passingNoonOrMidnight = (oldValue.equals("12") && newValue.equals("11")) || oldValue.equals("11") && newValue.equals("12"); |
|
|
|
|
|
if (passingNoonOrMidnight) ampmPicker.smoothScrollToValue((ampmPicker.getValue() + 1) % 2,false); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setMinimumDate(Date date) { |
|
|
|
|
|
minDate = DateUtils.truncate(date, Calendar.MINUTE); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setMaximumDate(Date date) { |
|
|
|
|
|
maxDate = DateUtils.truncate(date, Calendar.MINUTE); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setDate(Date date) { |
|
|
|
|
|
applyOnVisibleWheels(new SetDate(date)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setLocale(Locale locale) { |
|
|
|
|
|
this.locale = locale; |
|
|
|
|
|
dateFormat = new SimpleDateFormat(getDateFormatTemplate(), Locale.US); |
|
|
|
|
|
applyOnAllWheels(new Refresh()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setMinuteInterval(int interval) { |
|
|
|
|
|
this.minuteInterval = interval; |
|
|
|
|
|
applyOnVisibleWheels(new Refresh()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Rounding cal to closest minute interval |
|
|
|
|
|
public Calendar getInitialDate() { |
|
|
|
|
|
Calendar cal = Calendar.getInstance(); |
|
|
|
|
|
if(minuteInterval <= 1) return cal; |
|
|
|
|
|
int exactMinute = Integer.valueOf(minutesWheel.format.format(cal.getTime())); |
|
|
|
|
|
int diffSinceLastInterval = exactMinute % minuteInterval; |
|
|
|
|
|
int diffAhead = minuteInterval - diffSinceLastInterval; |
|
|
|
|
|
int diffBehind= -diffSinceLastInterval; |
|
|
|
|
|
boolean closerToPrevious = minuteInterval / 2 > diffSinceLastInterval; |
|
|
|
|
|
int diffToExactValue = closerToPrevious ? diffBehind : diffAhead; |
|
|
|
|
|
cal.add(Calendar.MINUTE, diffToExactValue); |
|
|
|
|
|
return (Calendar) cal.clone(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
private String getDateFormatTemplate() { |
|
|
private String getDateFormatTemplate() { |
|
|
return dayWheel.getFormatTemplate() + " " |
|
|
return dayWheel.getFormatTemplate() + " " |
|
|
+ hourWheel.getFormatTemplate() + " " |
|
|
+ hourWheel.getFormatTemplate() + " " |
|
|
+ minutesWheel.getFormatTemplate() |
|
|
+ minutesWheel.getFormatTemplate() |
|
|
+ ampmWheel.getFormatTemplate(); |
|
|
|
|
|
|
|
|
+ ampmWheel.getFormatTemplate(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private String getDateString() { |
|
|
private String getDateString() { |
|
@ -95,58 +164,36 @@ public class PickerView extends RelativeLayout { |
|
|
+ ampmWheel.getValue(); |
|
|
+ ampmWheel.getValue(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void setMinimumDate(Date date) { |
|
|
|
|
|
minDate = DateUtils.truncate(date, Calendar.MINUTE); |
|
|
|
|
|
|
|
|
public Collection<Wheel> getVisibleWheels() { |
|
|
|
|
|
Collection<Wheel> visibleWheels = new ArrayList<>(); |
|
|
|
|
|
for (Wheel wheel: getAllWheels()) { |
|
|
|
|
|
if (wheel.visible()) { |
|
|
|
|
|
visibleWheels.add(wheel); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return visibleWheels; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void setMaximumDate(Date date) { |
|
|
|
|
|
maxDate = DateUtils.truncate(date, Calendar.MINUTE); |
|
|
|
|
|
|
|
|
public List<Wheel> getAllWheels(){ |
|
|
|
|
|
return new ArrayList<>(Arrays.asList(dayWheel, hourWheel, minutesWheel, ampmWheel)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void setDate(Date date) { |
|
|
|
|
|
dayWheel.setValue(date); |
|
|
|
|
|
hourWheel.setValue(date); |
|
|
|
|
|
minutesWheel.setValue(date); |
|
|
|
|
|
ampmWheel.setValue(date); |
|
|
|
|
|
|
|
|
public void applyOnAllWheels(WheelFunction function) { |
|
|
|
|
|
for (Wheel wheel: getAllWheels()) function.apply(wheel); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void setLocale(Locale locale) { |
|
|
|
|
|
dayWheel.setLocale(locale); |
|
|
|
|
|
hourWheel.setLocale(locale); |
|
|
|
|
|
minutesWheel.setLocale(locale); |
|
|
|
|
|
ampmWheel.setLocale(locale); |
|
|
|
|
|
|
|
|
|
|
|
dateFormat = new SimpleDateFormat(getDateFormatTemplate(), Locale.US); |
|
|
|
|
|
|
|
|
public void applyOnVisibleWheels(WheelFunction function) { |
|
|
|
|
|
for (Wheel wheel: getVisibleWheels()) function.apply(wheel); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private final Runnable measureAndLayout = new Runnable() { |
|
|
|
|
|
@Override |
|
|
|
|
|
public void run() { |
|
|
|
|
|
measure( |
|
|
|
|
|
MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY), |
|
|
|
|
|
MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY)); |
|
|
|
|
|
layout(getLeft(), getTop(), getRight(), getBottom()); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public void requestLayout() { |
|
|
public void requestLayout() { |
|
|
super.requestLayout(); |
|
|
super.requestLayout(); |
|
|
post(measureAndLayout); |
|
|
post(measureAndLayout); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private void changeAmPmWhenPassingMidnightOrNoon(){ |
|
|
|
|
|
hourPicker.setOnValueChangeListenerInScrolling(new NumberPickerView.OnValueChangeListenerInScrolling() { |
|
|
|
|
|
@Override |
|
|
|
|
|
public void onValueChangeInScrolling(NumberPickerView picker, int oldVal, int newVal) { |
|
|
|
|
|
if(Utils.usesAmPm(hourWheel.getLocale())){ |
|
|
|
|
|
String oldValue = hourWheel.getValueAtIndex(oldVal); |
|
|
|
|
|
String newValue = hourWheel.getValueAtIndex(newVal); |
|
|
|
|
|
boolean passingNoonOrMidnight = (oldValue.equals("12") && newValue.equals("11")) || oldValue.equals("11") && newValue.equals("12"); |
|
|
|
|
|
if (passingNoonOrMidnight) ampmPicker.smoothScrollToValue((ampmPicker.getValue() + 1) % 2); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public WheelChangeListener getListener() { |
|
|
|
|
|
return onWheelChangeListener; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
} |