|
|
|
@ -30,6 +30,7 @@ import android.widget.NumberPicker;
|
|
|
|
|
|
|
|
|
|
public class DateTimePicker extends FrameLayout {
|
|
|
|
|
|
|
|
|
|
// 定义一些常量,包括默认开启状态、半天和一天的小时数、一周的天数、各个数字选择器的取值范围等
|
|
|
|
|
private static final boolean DEFAULT_ENABLE_STATE = true;
|
|
|
|
|
|
|
|
|
|
private static final int HOURS_IN_HALF_DAY = 12;
|
|
|
|
@ -46,29 +47,34 @@ public class DateTimePicker extends FrameLayout {
|
|
|
|
|
private static final int AMPM_SPINNER_MIN_VAL = 0;
|
|
|
|
|
private static final int AMPM_SPINNER_MAX_VAL = 1;
|
|
|
|
|
|
|
|
|
|
private final NumberPicker mDateSpinner;
|
|
|
|
|
private final NumberPicker mHourSpinner;
|
|
|
|
|
private final NumberPicker mMinuteSpinner;
|
|
|
|
|
private final NumberPicker mAmPmSpinner;
|
|
|
|
|
private Calendar mDate;
|
|
|
|
|
private final NumberPicker mDateSpinner; // 日期选择器
|
|
|
|
|
private final NumberPicker mHourSpinner; // 小时选择器
|
|
|
|
|
private final NumberPicker mMinuteSpinner; // 分钟选择器
|
|
|
|
|
private final NumberPicker mAmPmSpinner; // 上午/下午选择器
|
|
|
|
|
private Calendar mDate; // 日期对象
|
|
|
|
|
|
|
|
|
|
private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK];
|
|
|
|
|
private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK]; // 显示的日期字符串
|
|
|
|
|
|
|
|
|
|
private boolean mIsAm;
|
|
|
|
|
private boolean mIsAm; // 当前是上午还是下午
|
|
|
|
|
|
|
|
|
|
private boolean mIs24HourView;
|
|
|
|
|
private boolean mIs24HourView; // 是否以24小时制显示时间
|
|
|
|
|
|
|
|
|
|
private boolean mIsEnabled = DEFAULT_ENABLE_STATE;
|
|
|
|
|
private boolean mIsEnabled = DEFAULT_ENABLE_STATE; // 当前是否处于开启状态
|
|
|
|
|
|
|
|
|
|
private boolean mInitialising;
|
|
|
|
|
private boolean mInitialising; // 是否正在初始化
|
|
|
|
|
|
|
|
|
|
private OnDateTimeChangedListener mOnDateTimeChangedListener;
|
|
|
|
|
private OnDateTimeChangedListener mOnDateTimeChangedListener; // 日期时间变化监听器
|
|
|
|
|
|
|
|
|
|
// 定义一个日期选择监听器,用于在用户调整日期选择器后更新日期值,并回调日期时间变化监听器
|
|
|
|
|
private NumberPicker.OnValueChangeListener mOnDateChangedListener = new NumberPicker.OnValueChangeListener() {
|
|
|
|
|
// 当日期选择器的值改变时,更新日历的日期,更新日期显示,触发日期时间变化监听器
|
|
|
|
|
@Override
|
|
|
|
|
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
|
|
|
|
|
// 计算日期变化的天数,并更新日历对象
|
|
|
|
|
mDate.add(Calendar.DAY_OF_YEAR, newVal - oldVal);
|
|
|
|
|
// 更新日期选择器显示的日期
|
|
|
|
|
updateDateControl();
|
|
|
|
|
// 通知监听器选择的日期时间发生变化
|
|
|
|
|
onDateTimeChanged();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
@ -115,52 +121,77 @@ public class DateTimePicker extends FrameLayout {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() {
|
|
|
|
|
// 定义一个小时选择监听器,用于在用户调整小时选择器后更新日期时间值,并回调日期时间变化监听器
|
|
|
|
|
private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() {
|
|
|
|
|
// 当小时选择器的值发生改变时,更新日期时间对象,并触发日期时间变化监听器
|
|
|
|
|
@Override
|
|
|
|
|
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
|
|
|
|
|
int minValue = mMinuteSpinner.getMinValue();
|
|
|
|
|
int maxValue = mMinuteSpinner.getMaxValue();
|
|
|
|
|
int offset = 0;
|
|
|
|
|
if (oldVal == maxValue && newVal == minValue) {
|
|
|
|
|
offset += 1;
|
|
|
|
|
} else if (oldVal == minValue && newVal == maxValue) {
|
|
|
|
|
offset -= 1;
|
|
|
|
|
}
|
|
|
|
|
if (offset != 0) {
|
|
|
|
|
mDate.add(Calendar.HOUR_OF_DAY, offset);
|
|
|
|
|
mHourSpinner.setValue(getCurrentHour());
|
|
|
|
|
updateDateControl();
|
|
|
|
|
int newHour = getCurrentHourOfDay();
|
|
|
|
|
if (newHour >= HOURS_IN_HALF_DAY) {
|
|
|
|
|
mIsAm = false;
|
|
|
|
|
updateAmPmControl();
|
|
|
|
|
} else {
|
|
|
|
|
mIsAm = true;
|
|
|
|
|
boolean isDateChanged = false; // 标识日期是否发生了变化
|
|
|
|
|
Calendar cal = Calendar.getInstance(); // 创建当前日期时间对象
|
|
|
|
|
|
|
|
|
|
// 根据当前是否是24小时制和是否跨越上下午进行不同的变化处理和计算
|
|
|
|
|
if (!mIs24HourView) { // 不是24小时制
|
|
|
|
|
if (!mIsAm && oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) { // 跨越中午
|
|
|
|
|
cal.setTimeInMillis(mDate.getTimeInMillis());
|
|
|
|
|
cal.add(Calendar.DAY_OF_YEAR, 1); // 将日期向后推一天
|
|
|
|
|
isDateChanged = true;
|
|
|
|
|
} else if (mIsAm && oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) { // 跨越中午
|
|
|
|
|
cal.setTimeInMillis(mDate.getTimeInMillis());
|
|
|
|
|
cal.add(Calendar.DAY_OF_YEAR, -1); // 将日期向前推一天
|
|
|
|
|
isDateChanged = true;
|
|
|
|
|
}
|
|
|
|
|
if (oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY || oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) {
|
|
|
|
|
// 跨越中午后需要更新上午/下午的显示
|
|
|
|
|
mIsAm = !mIsAm;
|
|
|
|
|
updateAmPmControl();
|
|
|
|
|
}
|
|
|
|
|
} else { // 是24小时制
|
|
|
|
|
if (oldVal == HOURS_IN_ALL_DAY - 1 && newVal == 0) { // 跨越0点
|
|
|
|
|
cal.setTimeInMillis(mDate.getTimeInMillis());
|
|
|
|
|
cal.add(Calendar.DAY_OF_YEAR, 1); // 将日期向后推一天
|
|
|
|
|
isDateChanged = true;
|
|
|
|
|
} else if (oldVal == 0 && newVal == HOURS_IN_ALL_DAY - 1) { // 跨越0点
|
|
|
|
|
cal.setTimeInMillis(mDate.getTimeInMillis());
|
|
|
|
|
cal.add(Calendar.DAY_OF_YEAR, -1); // 将日期向前推一天
|
|
|
|
|
isDateChanged = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 根据当前是否为上午、24小时制和选择的小时数计算出新的小时数
|
|
|
|
|
int newHour = mHourSpinner.getValue() % HOURS_IN_HALF_DAY + (mIsAm ? 0 : HOURS_IN_HALF_DAY);
|
|
|
|
|
mDate.set(Calendar.HOUR_OF_DAY, newHour); // 更新日历对象中的小时数
|
|
|
|
|
onDateTimeChanged(); // 通知监听器日期时间变化事件
|
|
|
|
|
|
|
|
|
|
if (isDateChanged) {
|
|
|
|
|
// 如果日期发生变化,则需要更新日期选择器的显示
|
|
|
|
|
setCurrentYear(cal.get(Calendar.YEAR));
|
|
|
|
|
setCurrentMonth(cal.get(Calendar.MONTH));
|
|
|
|
|
setCurrentDay(cal.get(Calendar.DAY_OF_MONTH));
|
|
|
|
|
}
|
|
|
|
|
mDate.set(Calendar.MINUTE, newVal);
|
|
|
|
|
onDateTimeChanged();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
|
|
|
|
|
// 每次选择AM/PM时,切换mIsAm标志位
|
|
|
|
|
mIsAm = !mIsAm;
|
|
|
|
|
// 根据选择的AM/PM更新时间
|
|
|
|
|
if (mIsAm) {
|
|
|
|
|
mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY);
|
|
|
|
|
} else {
|
|
|
|
|
mDate.add(Calendar.HOUR_OF_DAY, HOURS_IN_HALF_DAY);
|
|
|
|
|
}
|
|
|
|
|
// 更新AM/PM控件的状态
|
|
|
|
|
updateAmPmControl();
|
|
|
|
|
// 回调onDateTimeChanged方法,通知监听器时间发生了变化
|
|
|
|
|
onDateTimeChanged();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public interface OnDateTimeChangedListener {
|
|
|
|
|
// 定义onDateTimeChanged方法
|
|
|
|
|
void onDateTimeChanged(DateTimePicker view, int year, int month,
|
|
|
|
|
int dayOfMonth, int hourOfDay, int minute);
|
|
|
|
|
int dayOfMonth, int hourOfDay, int minute);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public DateTimePicker(Context context) {
|
|
|
|
|