You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
miNote2/java/net/micode/notes/ui/DateTimePicker.java

745 lines
26 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 版权声明和许可证信息:
* 该代码遵循 Apache License 2.0 协议,由 MiCode 开源社区提供。
*/
package net.micode.notes.ui;
import java.text.DateFormatSymbols;
import java.util.Calendar;
import net.micode.notes.R;
import android.content.Context;
import android.text.format.DateFormat;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.NumberPicker;
/**
* DateTimePicker 是一个自定义的日期时间选择控件,继承自 FrameLayout。
*/
public class DateTimePicker extends FrameLayout {
// 默认启用状态
private static final boolean DEFAULT_ENABLE_STATE = true;
// 一天中的小时数12小时制
private static final int HOURS_IN_HALF_DAY = 12;
// 一天中的小时数24小时制
private static final int HOURS_IN_ALL_DAY = 24;
// 一周中的天数
private static final int DAYS_IN_ALL_WEEK = 7;
// 日期选择器的最小值
private static final int DATE_SPINNER_MIN_VAL = 0;
// 日期选择器的最大值(一周的天数减一)
private static final int DATE_SPINNER_MAX_VAL = DAYS_IN_ALL_WEEK - 1;
// 24小时制下小时选择器的最小值
private static final int HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW = 0;
// 24小时制下小时选择器的最大值
private static final int HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW = 23;
// 12小时制下小时选择器的最小值
private static final int HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW = 1;
// 12小时制下小时选择器的最大值
private static final int HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW = 12;
// 分钟选择器的最小值
private static final int MINUT_SPINNER_MIN_VAL = 0;
// 分钟选择器的最大值
private static final int MINUT_SPINNER_MAX_VAL = 59;
// 上午/下午选择器的最小值
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 String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK];
// 是否是上午
private boolean mIsAm;
// 是否为24小时制视图
private boolean mIs24HourView;
// 控件是否启用
private boolean mIsEnabled = DEFAULT_ENABLE_STATE;
// 是否正在初始化
private boolean mInitialising;
// 日期时间变化监听器
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();
}
};
// 小时选择器值变化监听器
private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
boolean isDateChanged = false;
Calendar cal = Calendar.getInstance();
if (!mIs24HourView) {
// 处理12小时制下的日期变化
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) {
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, 1);
isDateChanged = true;
} else if (oldVal == 0 && newVal == HOURS_IN_ALL_DAY - 1) {
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, -1);
isDateChanged = true;
}
}
// 更新小时并设置到日历对象中
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));
}
}
};
/**
* 分钟选择器值变化监听器,用于处理分钟变化时的逻辑。
*/
private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
// 获取分钟选择器的最小值和最大值0 和 59
int minValue = mMinuteSpinner.getMinValue();
int maxValue = mMinuteSpinner.getMaxValue();
int offset = 0;
/*
* 如果分钟从最大值变为最小值(如 59 -> 0表示时间向前推进了一小时
* 如果分钟从最小值变为最大值(如 0 -> 59表示时间回退了一小时。
*/
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();
// 获取当前小时24小时制
int newHour = getCurrentHourOfDay();
/*
* 根据当前小时判断是 AM 还是 PM并更新 AM/PM 选择器的状态:
* - 如果小时 >= 12则为 PM
* - 否则为 AM。
*/
if (newHour >= HOURS_IN_HALF_DAY) {
mIsAm = false;
updateAmPmControl(); // 更新 AM/PM 显示
} else {
mIsAm = true;
updateAmPmControl(); // 更新 AM/PM 显示
}
}
// 设置新的分钟值到日历对象中
mDate.set(Calendar.MINUTE, newVal);
// 触发日期时间变化的回调
onDateTimeChanged();
}
};
/**
* AM/PM 选择器值变化监听器,用于处理 AM/PM 切换时的时间调整逻辑。
*/
private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
// 切换 AM/PM 状态true 表示 AMfalse 表示 PM
mIsAm = !mIsAm;
// 根据当前是 AM 还是 PM 调整小时数:
if (mIsAm) {
// 如果切换为 AM则减去 12 小时
mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY);
} else {
// 如果切换为 PM则加上 12 小时
mDate.add(Calendar.HOUR_OF_DAY, HOURS_IN_HALF_DAY);
}
// 更新 AM/PM 控件显示状态
updateAmPmControl();
// 通知外部监听器日期时间已发生变化
onDateTimeChanged();
}
};
/**
* 日期时间变化监听器接口,用于通知外部监听者日期或时间发生了变化。
*/
public interface OnDateTimeChangedListener {
/**
* 当日期或时间发生变化时调用此方法。
*
* @param view 发生变化的 DateTimePicker 实例
* @param year 当前选择的年份
* @param month 当前选择的月份0 表示一月)
* @param dayOfMonth 当前选择的日期(月份中的第几天)
* @param hourOfDay 当前选择的小时24小时制
* @param minute 当前选择的分钟
*/
void onDateTimeChanged(DateTimePicker view, int year, int month,
int dayOfMonth, int hourOfDay, int minute);
}
/**
* 构造函数:使用默认的时间(当前系统时间)创建一个 DateTimePicker 实例。
*/
public DateTimePicker(Context context) {
this(context, System.currentTimeMillis());
}
/**
* 构造函数:使用指定的时间创建 DateTimePicker 实例,
* 并根据系统设置自动判断是否使用 24 小时制。
*
* @param context 上下文环境,通常为 Activity 或 Application
* @param date 初始时间,以毫秒为单位的时间戳
*/
public DateTimePicker(Context context, long date) {
this(context, date, DateFormat.is24HourFormat(context));
}
/**
* 完整构造函数:创建 DateTimePicker 实例,并初始化所有 UI 组件和逻辑。
*
* @param context 上下文环境
* @param date 初始时间,以毫秒为单位的时间戳
* @param is24HourView 是否使用 24 小时制显示时间
*/
public DateTimePicker(Context context, long date, boolean is24HourView) {
super(context);
// 初始化 Calendar 对象,用于保存当前选择的日期时间
mDate = Calendar.getInstance();
// 标记为正在初始化中(避免监听器在初始化过程中触发不必要的回调)
mInitialising = true;
// 判断当前是否为 AM小时 >= 12 表示 PM
mIsAm = getCurrentHourOfDay() >= HOURS_IN_HALF_DAY;
// 加载布局文件 R.layout.datetime_picker 并添加到当前 FrameLayout 中
inflate(context, R.layout.datetime_picker, this);
// 初始化日期选择器 NumberPicker
mDateSpinner = (NumberPicker) findViewById(R.id.date);
mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL); // 设置最小值为 0
mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL); // 设置最大值为 6一周7天
mDateSpinner.setOnValueChangedListener(mOnDateChangedListener); // 设置监听器
// 初始化小时选择器 NumberPicker
mHourSpinner = (NumberPicker) findViewById(R.id.hour);
mHourSpinner.setOnValueChangedListener(mOnHourChangedListener); // 设置监听器
// 初始化分钟选择器 NumberPicker
mMinuteSpinner = (NumberPicker) findViewById(R.id.minute);
mMinuteSpinner.setMinValue(MINUT_SPINNER_MIN_VAL); // 设置最小值为 0
mMinuteSpinner.setMaxValue(MINUT_SPINNER_MAX_VAL); // 设置最大值为 59
mMinuteSpinner.setOnLongPressUpdateInterval(100); // 长按递增间隔时间为 100ms
mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener); // 设置监听器
// 获取 AM/PM 的本地化字符串(如 "AM", "PM"
String[] stringsForAmPm = new DateFormatSymbols().getAmPmStrings();
// 初始化 AM/PM 选择器 NumberPicker
mAmPmSpinner = (NumberPicker) findViewById(R.id.amPm);
mAmPmSpinner.setMinValue(AMPM_SPINNER_MIN_VAL); // 设置最小值为 0
mAmPmSpinner.setMaxValue(AMPM_SPINNER_MAX_VAL); // 设置最大值为 1
mAmPmSpinner.setDisplayedValues(stringsForAmPm); // 设置显示值为 "AM"/"PM"
mAmPmSpinner.setOnValueChangedListener(mOnAmPmChangedListener); // 设置监听器
// 初始化各控件的显示状态
updateDateControl(); // 更新日期选择器显示
updateHourControl(); // 更新小时选择器显示
updateAmPmControl(); // 更新 AM/PM 显示状态
// 设置是否启用 24 小时制视图
set24HourView(is24HourView);
// 设置初始日期时间
setCurrentDate(date);
// 设置控件的启用状态
setEnabled(isEnabled());
// 设置内容描述等辅助功能信息(未展示具体实现)
// 结束初始化过程
mInitialising = false;
}
/**
* 重写 setEnabled 方法,用于控制 DateTimePicker 及其内部所有子控件的启用/禁用状态。
*
* @param enabled true 表示启用false 表示禁用
*/
@Override
public void setEnabled(boolean enabled) {
// 如果当前状态与目标状态相同,则无需处理
if (mIsEnabled == enabled) {
return;
}
// 调用父类方法设置自身启用状态
super.setEnabled(enabled);
// 设置各个 NumberPicker 子控件的启用状态
mDateSpinner.setEnabled(enabled); // 日期选择器
mMinuteSpinner.setEnabled(enabled); // 分钟选择器
mHourSpinner.setEnabled(enabled); // 小时选择器
mAmPmSpinner.setEnabled(enabled); // AM/PM 选择器
// 更新当前控件的启用状态标志
mIsEnabled = enabled;
}
/**
* 重写 isEnabled 方法,返回当前控件的启用状态。
*
* @return 如果控件可用则返回 true否则返回 false
*/
@Override
public boolean isEnabled() {
return mIsEnabled; // 返回内部保存的启用状态标志
}
/**
* 获取当前选择的日期时间(以毫秒为单位的时间戳)。
*
* @return 当前日期时间对应的毫秒值
*/
public long getCurrentDateInTimeMillis() {
return mDate.getTimeInMillis(); // 返回 Calendar 对象中的时间戳
}
/**
* 设置当前日期时间。
*
* @param date 给定的初始时间,以毫秒为单位的时间戳
*/
public void setCurrentDate(long date) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(date); // 将时间戳转换为 Calendar 对象
// 调用另一个方法设置年、月、日、小时、分钟
setCurrentDate(cal.get(Calendar.YEAR),
cal.get(Calendar.MONTH),
cal.get(Calendar.DAY_OF_MONTH),
cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE));
}
/**
* Set the current date
*
* @param year The current year
* @param month The current month
* @param dayOfMonth The current dayOfMonth
* @param hourOfDay The current hourOfDay
* @param minute The current minute
*/
/**
* 设置当前日期和时间。
*
* @param year 年份(例如 2025
* @param month 月份0 表示一月11 表示十二月)
* @param dayOfMonth 月份中的第几天(从 1 开始)
* @param hourOfDay 小时24小时制0~23
* @param minute 分钟0~59
*/
public void setCurrentDate(int year, int month, int dayOfMonth, int hourOfDay, int minute) {
// 设置年份
setCurrentYear(year);
// 设置月份
setCurrentMonth(month);
// 设置日
setCurrentDay(dayOfMonth);
// 设置小时
setCurrentHour(hourOfDay);
// 设置分钟
setCurrentMinute(minute);
}
/**
* Get current year
*
* @return The current year
*/
/**
* 获取当前选择的年份。
*
* @return 返回当前 Calendar 对象中的年份值(例如 2025
*/
public int getCurrentYear() {
return mDate.get(Calendar.YEAR);
}
/**
* 设置当前选择的年份,并更新相关的 UI 控件和监听器。
*
* @param year 要设置的年份,例如 2025
*/
public void setCurrentYear(int year) {
// 如果不是初始化阶段,并且新值与当前年份相同,则无需处理
if (!mInitialising && year == getCurrentYear()) {
return;
}
// 更新 Calendar 对象中的年份
mDate.set(Calendar.YEAR, year);
// 更新日期控件(如 NumberPicker 显示)
updateDateControl();
// 触发日期时间变化的回调事件
onDateTimeChanged();
}
/**
* 获取当前选择的月份。
*
* @return 返回当前 Calendar 对象中的月份值0 表示一月11 表示十二月)
*/
public int getCurrentMonth() {
return mDate.get(Calendar.MONTH);
}
/**
* 设置当前选择的月份,并更新相关的 UI 控件和监听器。
*
* @param month 要设置的月份0 表示一月11 表示十二月)
*/
public void setCurrentMonth(int month) {
// 如果不是初始化阶段,并且新值与当前月份相同,则无需处理
if (!mInitialising && month == getCurrentMonth()) {
return;
}
// 更新 Calendar 对象中的月份
mDate.set(Calendar.MONTH, month);
// 更新日期控件(如星期几等显示内容)
updateDateControl();
// 触发日期时间变化的回调事件
onDateTimeChanged();
}
/**
* 获取当前选择的日期(即一个月中的第几天)。
*
* @return 返回当前 Calendar 对象中的日值1 ~ 31
*/
public int getCurrentDay() {
return mDate.get(Calendar.DAY_OF_MONTH);
}
/**
* 设置当前选择的日期(即一个月中的第几天)。
*
* @param dayOfMonth 要设置的具体日期,范围为 1 ~ 31
*/
public void setCurrentDay(int dayOfMonth) {
// 如果不是初始化阶段,并且新值与当前日期相同,则无需处理
if (!mInitialising && dayOfMonth == getCurrentDay()) {
return;
}
// 更新 Calendar 对象中的日期(即月中的第几天)
mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
// 更新日期控件(如星期几等显示内容)
updateDateControl();
// 触发日期时间变化的回调事件
onDateTimeChanged();
}
/**
* 获取当前小时24小时制
*
* @return 返回 Calendar 对象中的小时值0 ~ 23
*/
public int getCurrentHourOfDay() {
return mDate.get(Calendar.HOUR_OF_DAY);
}
/**
* 获取当前显示用的小时值,根据是否为 24 小时视图返回不同的格式。
*
* @return 返回适合显示的小时值24小时制直接返回12小时制则转换为 1 ~ 12
*/
private int getCurrentHour() {
if (mIs24HourView) {
// 如果是 24 小时视图,直接返回 0~23 的小时值
return getCurrentHourOfDay();
} else {
int hour = getCurrentHourOfDay();
if (hour > HOURS_IN_HALF_DAY) {
// 下午:将 13~23 转换为 1~11
return hour - HOURS_IN_HALF_DAY;
} else {
// 上午0 转换为 12其他保持原样1~11
return hour == 0 ? HOURS_IN_HALF_DAY : hour;
}
}
}
/**
* 设置当前小时24小时制并根据视图模式更新 UI 显示。
*
* @param hourOfDay 要设置的小时值0 ~ 23
*/
public void setCurrentHour(int hourOfDay) {
// 如果不是初始化阶段,且新值与当前小时相同,则无需处理
if (!mInitialising && hourOfDay == getCurrentHourOfDay()) {
return;
}
// 更新 Calendar 对象中的小时24小时制
mDate.set(Calendar.HOUR_OF_DAY, hourOfDay);
// 如果是 12 小时制视图,需要处理 AM/PM 和显示值
if (!mIs24HourView) {
if (hourOfDay >= HOURS_IN_HALF_DAY) {
// 下午12~23
mIsAm = false;
if (hourOfDay > HOURS_IN_HALF_DAY) {
// 13~23 转换为 1~11
hourOfDay -= HOURS_IN_HALF_DAY;
}
// else: hourOfDay == 12 → 不变
} else {
// 上午0~11
mIsAm = true;
if (hourOfDay == 0) {
// 0 点显示为 12 AM
hourOfDay = HOURS_IN_HALF_DAY; // 12
}
// else: 1~11 → 不变
}
// 更新 AM/PM 控件显示状态
updateAmPmControl();
}
// 设置小时选择器的显示值NumberPicker
mHourSpinner.setValue(hourOfDay);
// 触发日期时间变化回调
onDateTimeChanged();
}
/**
* 获取当前选择的分钟值。
*
* @return 返回 Calendar 对象中的分钟值0 ~ 59
*/
public int getCurrentMinute() {
return mDate.get(Calendar.MINUTE);
}
/**
* 设置当前选择的分钟值,并更新内部时间模型和监听器。
*
* @param minute 要设置的分钟值0 ~ 59
*/
public void setCurrentMinute(int minute) {
// 如果不是初始化阶段,且新值与当前分钟相同,则无需处理
if (!mInitialising && minute == getCurrentMinute()) {
return;
}
// 更新分钟选择器 NumberPicker 的显示值
mMinuteSpinner.setValue(minute);
// 更新 Calendar 对象中的分钟值
mDate.set(Calendar.MINUTE, minute);
// 触发日期时间变化的回调事件
onDateTimeChanged();
}
/**
* 判断当前是否为 24 小时制视图。
*
* @return 如果是 24 小时制返回 true否则返回 false
*/
public boolean is24HourView () {
return mIs24HourView;
}
/**
* 设置是否使用 24 小时制显示时间。
*
* @param is24HourView true 表示使用 24 小时制false 表示使用 AM/PM 模式
*/
public void set24HourView(boolean is24HourView) {
if (mIs24HourView == is24HourView) {
return; // 如果状态未变,无需处理
}
mIs24HourView = is24HourView;
// 根据模式切换 AM/PM 控件的可见性
mAmPmSpinner.setVisibility(is24HourView ? View.GONE : View.VISIBLE);
int hour = getCurrentHourOfDay(); // 获取当前小时
updateHourControl(); // 更新小时选择器范围12/24
setCurrentHour(hour); // 重新设置小时以适配新视图
updateAmPmControl(); // 更新 AM/PM 显示状态
}
/**
* 更新日期选择器的显示内容显示一周内的日期格式MM.dd EEEE
*/
private void updateDateControl() {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, -DAYS_IN_ALL_WEEK / 2 - 1); // 回退几天,构建一周范围
mDateSpinner.setDisplayedValues(null); // 清空旧数据
for (int i = 0; i < DAYS_IN_ALL_WEEK; ++i) {
cal.add(Calendar.DAY_OF_YEAR, 1);
mDateDisplayValues[i] = (String) DateFormat.format("MM.dd EEEE", cal);
}
mDateSpinner.setDisplayedValues(mDateDisplayValues); // 设置新数据显示
mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2); // 默认选中中间日期
mDateSpinner.invalidate(); // 刷新控件
}
/**
* 更新 AM/PM 选择器的状态和显示。
*/
private void updateAmPmControl() {
if (mIs24HourView) {
mAmPmSpinner.setVisibility(View.GONE); // 24小时制隐藏 AM/PM
} else {
int index = mIsAm ? Calendar.AM : Calendar.PM;
mAmPmSpinner.setValue(index); // 设置当前 AM/PM 状态
mAmPmSpinner.setVisibility(View.VISIBLE); // 显示 AM/PM 控件
}
}
/**
* 根据当前时间格式12/24小时制设置小时选择器的取值范围。
*/
private void updateHourControl() {
if (mIs24HourView) {
mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW); // 0
mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW); // 23
} else {
mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW); // 1
mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW); // 12
}
}
/**
* 设置日期时间变化监听器。
*
* @param callback 监听器对象,如果为 null 则不触发回调
*/
public void setOnDateTimeChangedListener(OnDateTimeChangedListener callback) {
mOnDateTimeChangedListener = callback;
}
/**
* 触发日期时间变化回调。
*/
private void onDateTimeChanged() {
if (mOnDateTimeChangedListener != null) {
mOnDateTimeChangedListener.onDateTimeChanged(this, getCurrentYear(),
getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute());
}
}
}