|  |  | @ -16,22 +16,46 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | package net.micode.notes.ui; |  |  |  | package net.micode.notes.ui; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | import java.text.DateFormatSymbols; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | import java.util.Calendar; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | import net.micode.notes.R; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | import android.content.Context; |  |  |  | import android.content.Context; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | import android.os.Build; | 
			
		
	
		
		
			
				
					
					|  |  |  | import android.text.format.DateFormat; |  |  |  | import android.text.format.DateFormat; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | import android.util.AttributeSet; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | import android.util.Log; | 
			
		
	
		
		
			
				
					
					|  |  |  | import android.view.View; |  |  |  | import android.view.View; | 
			
		
	
		
		
			
				
					
					|  |  |  | import android.widget.FrameLayout; |  |  |  | import android.widget.FrameLayout; | 
			
		
	
		
		
			
				
					
					|  |  |  | import android.widget.NumberPicker; |  |  |  | import android.widget.NumberPicker; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | import android.widget.Toast; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | import net.micode.notes.R; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | import java.text.DateFormatSymbols; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | import java.util.Calendar; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | import java.util.Locale; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 日期时间选择器控件 - 提供完整的日期和时间选择功能 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  *  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 功能增强: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 1. 支持日期范围限制 (设置最小/最大日期) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 2. 添加星期名称本地化处理 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 3. 支持日期格式化定制 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 4. 增加日期验证和错误提示 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 5. 改进时间滚动逻辑 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 6. 支持深色模式 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 7. 添加无障碍支持 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  *  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 修复问题: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 1. 修复12/24小时转换逻辑错误 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 2. 解决日期显示越界问题 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 3. 优化AM/PM切换处理 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * 4. 改进初始状态标记处理 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  */ | 
			
		
	
		
		
			
				
					
					|  |  |  | public class DateTimePicker extends FrameLayout { |  |  |  | public class DateTimePicker extends FrameLayout { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     private static final boolean DEFAULT_ENABLE_STATE = true; |  |  |  |     private static final String TAG = "DateTimePicker"; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // 配置常量
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private static final boolean DEFAULT_ENABLE_STATE = true; | 
			
		
	
		
		
			
				
					
					|  |  |  |     private static final int HOURS_IN_HALF_DAY = 12; |  |  |  |     private static final int HOURS_IN_HALF_DAY = 12; | 
			
		
	
		
		
			
				
					
					|  |  |  |     private static final int HOURS_IN_ALL_DAY = 24; |  |  |  |     private static final int HOURS_IN_ALL_DAY = 24; | 
			
		
	
		
		
			
				
					
					|  |  |  |     private static final int DAYS_IN_ALL_WEEK = 7; |  |  |  |     private static final int DAYS_IN_ALL_WEEK = 7; | 
			
		
	
	
		
		
			
				
					|  |  | @ -41,130 +65,114 @@ public class DateTimePicker extends FrameLayout { | 
			
		
	
		
		
			
				
					
					|  |  |  |     private static final int HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW = 23; |  |  |  |     private static final int HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW = 23; | 
			
		
	
		
		
			
				
					
					|  |  |  |     private static final int HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW = 1; |  |  |  |     private static final int HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW = 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |     private static final int HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW = 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 MINUTE_SPINNER_MIN_VAL = 0; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     private static final int MINUT_SPINNER_MAX_VAL = 59; |  |  |  |     private static final int MINUTE_SPINNER_MAX_VAL = 59; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     private static final int AMPM_SPINNER_MIN_VAL = 0; |  |  |  |     private static final int AMPM_SPINNER_MIN_VAL = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |     private static final int AMPM_SPINNER_MAX_VAL = 1; |  |  |  |     private static final int AMPM_SPINNER_MAX_VAL = 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |      |  |  |  |      | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // 状态常量
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private static final int MODE_INITIALIZING = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private static final int MODE_NORMAL = 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // 范围限制 (默认无限制)
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private long mMinDate = Long.MIN_VALUE; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private long mMaxDate = Long.MAX_VALUE; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // UI组件
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     private final NumberPicker mDateSpinner; |  |  |  |     private final NumberPicker mDateSpinner; | 
			
		
	
		
		
			
				
					
					|  |  |  |     private final NumberPicker mHourSpinner; |  |  |  |     private final NumberPicker mHourSpinner; | 
			
		
	
		
		
			
				
					
					|  |  |  |     private final NumberPicker mMinuteSpinner; |  |  |  |     private final NumberPicker mMinuteSpinner; | 
			
		
	
		
		
			
				
					
					|  |  |  |     private final NumberPicker mAmPmSpinner; |  |  |  |     private final NumberPicker mAmPmSpinner; | 
			
		
	
		
		
			
				
					
					|  |  |  |     private Calendar mDate; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      |  |  |  |      | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // 数据模型
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     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; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     private boolean mIsEnabled = DEFAULT_ENABLE_STATE; |  |  |  |     private boolean mIsEnabled = DEFAULT_ENABLE_STATE; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private int mState = MODE_INITIALIZING; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     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); |  |  |  |     private final NumberPicker.OnValueChangeListener mOnDateChangedListener =  | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         (picker, oldVal, newVal) -> { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             // 计算日期变化差值
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             int dayDiff = newVal - oldVal; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             mDate.add(Calendar.DAY_OF_YEAR, dayDiff); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |              | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             // 验证日期范围
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (!isDateInRange()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 revertDateChange(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 showDateRangeWarning(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 return; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |              | 
			
		
	
		
		
			
				
					
					|  |  |  |             updateDateControl(); |  |  |  |             updateDateControl(); | 
			
		
	
		
		
			
				
					
					|  |  |  |             onDateTimeChanged(); |  |  |  |             onDateTimeChanged(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         }; |  |  |  |         }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() { |  |  |  |     /** | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         @Override |  |  |  |      * 小时变更监听器 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         public void onValueChange(NumberPicker picker, int oldVal, int newVal) { |  |  |  |      */ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             boolean isDateChanged = false; |  |  |  |     private final NumberPicker.OnValueChangeListener mOnHourChangedListener =  | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             Calendar cal = Calendar.getInstance(); |  |  |  |         (picker, oldVal, newVal) -> { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             if (!mIs24HourView) { |  |  |  |             int newHour = computeNewHour(oldVal, newVal); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 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 { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 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); |  |  |  |             mDate.set(Calendar.HOUR_OF_DAY, newHour); | 
			
		
	
		
		
			
				
					
					|  |  |  |             onDateTimeChanged(); |  |  |  |             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) { |  |  |  |      */ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             int minValue = mMinuteSpinner.getMinValue(); |  |  |  |     private final NumberPicker.OnValueChangeListener mOnMinuteChangedListener =  | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             int maxValue = mMinuteSpinner.getMaxValue(); |  |  |  |         (picker, oldVal, newVal) -> { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             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; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     updateAmPmControl(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             mDate.set(Calendar.MINUTE, newVal); |  |  |  |             mDate.set(Calendar.MINUTE, newVal); | 
			
		
	
		
		
			
				
					
					|  |  |  |             onDateTimeChanged(); |  |  |  |             onDateTimeChanged(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         }; |  |  |  |         }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() { |  |  |  |     /** | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         @Override |  |  |  |      * AM/PM变更监听器 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         public void onValueChange(NumberPicker picker, int oldVal, int newVal) { |  |  |  |      */ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             mIsAm = !mIsAm; |  |  |  |     private final NumberPicker.OnValueChangeListener mOnAmPmChangedListener =  | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             if (mIsAm) { |  |  |  |         (picker, oldVal, newVal) -> { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY); |  |  |  |             // 切换AM/PM状态
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             } else { |  |  |  |             mIsAm = (newVal == Calendar.AM); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 mDate.add(Calendar.HOUR_OF_DAY, HOURS_IN_HALF_DAY); |  |  |  |              | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             // 调整时间:AM->PM加12小时,PM->AM减12小时
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             updateAmPmControl(); |  |  |  |             int hour = mDate.get(Calendar.HOUR_OF_DAY); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             hour = mIsAm ? hour % 12 : hour % 12 + 12; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             mDate.set(Calendar.HOUR_OF_DAY, hour); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |              | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             updateHourControl(); | 
			
		
	
		
		
			
				
					
					|  |  |  |             onDateTimeChanged(); |  |  |  |             onDateTimeChanged(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         }; |  |  |  |         }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 日期时间变更回调接口 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public interface OnDateTimeChangedListener { |  |  |  |     public interface OnDateTimeChangedListener { | 
			
		
	
		
		
			
				
					
					|  |  |  |         void onDateTimeChanged(DateTimePicker view, int year, int month, |  |  |  |         void onDateTimeChanged(DateTimePicker view, int year, int month, | 
			
		
	
		
		
			
				
					
					|  |  |  |                 int dayOfMonth, int hourOfDay, int minute); |  |  |  |                 int dayOfMonth, int hourOfDay, int minute); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /*************************** 构造函数 ***************************/ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     public DateTimePicker(Context context) { |  |  |  |     public DateTimePicker(Context context) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         this(context, System.currentTimeMillis()); |  |  |  |         this(context, null); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public DateTimePicker(Context context, AttributeSet attrs) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         this(context, attrs, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public DateTimePicker(Context context, AttributeSet attrs, int defStyleAttr) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         super(context, attrs, defStyleAttr); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 使用当前时间初始化
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         init(context, System.currentTimeMillis(), DateFormat.is24HourFormat(context)); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     public DateTimePicker(Context context, long date) { |  |  |  |     public DateTimePicker(Context context, long date) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -173,57 +181,85 @@ public class DateTimePicker extends FrameLayout { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     public DateTimePicker(Context context, long date, boolean is24HourView) { |  |  |  |     public DateTimePicker(Context context, long date, boolean is24HourView) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         super(context); |  |  |  |         super(context); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         init(context, date, is24HourView); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 初始化日期时间选择器 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private void init(Context context, long date, boolean is24HourView) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 初始化日期对象
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         mDate = Calendar.getInstance(); |  |  |  |         mDate = Calendar.getInstance(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mInitialising = true; |  |  |  |         mState = MODE_INITIALIZING; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         mIsAm = getCurrentHourOfDay() >= HOURS_IN_HALF_DAY; |  |  |  |         mIs24HourView = is24HourView; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 确定初始AM/PM状态
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         int currentHour = (int) (date / (60 * 60 * 1000) % 24); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mIsAm = currentHour < 12; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 加载布局
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         inflate(context, R.layout.datetime_picker, this); |  |  |  |         inflate(context, R.layout.datetime_picker, this); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         mDateSpinner = (NumberPicker) findViewById(R.id.date); |  |  |  |         // 初始化日期选择器
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mDateSpinner = findViewById(R.id.date); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL); |  |  |  |         mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL); |  |  |  |         mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mDateSpinner.setOnValueChangedListener(mOnDateChangedListener); |  |  |  |         mDateSpinner.setOnValueChangedListener(mOnDateChangedListener); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mDateSpinner.setWrapSelectorWheel(false); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         mHourSpinner = (NumberPicker) findViewById(R.id.hour); |  |  |  |         // 初始化小时选择器
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mHourSpinner = findViewById(R.id.hour); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mHourSpinner.setOnValueChangedListener(mOnHourChangedListener); |  |  |  |         mHourSpinner.setOnValueChangedListener(mOnHourChangedListener); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mMinuteSpinner =  (NumberPicker) findViewById(R.id.minute); |  |  |  | 
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         mMinuteSpinner.setMinValue(MINUT_SPINNER_MIN_VAL); |  |  |  |         // 初始化分钟选择器
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         mMinuteSpinner.setMaxValue(MINUT_SPINNER_MAX_VAL); |  |  |  |         mMinuteSpinner = findViewById(R.id.minute); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mMinuteSpinner.setMinValue(MINUTE_SPINNER_MIN_VAL); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mMinuteSpinner.setMaxValue(MINUTE_SPINNER_MAX_VAL); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mMinuteSpinner.setOnLongPressUpdateInterval(100); |  |  |  |         mMinuteSpinner.setOnLongPressUpdateInterval(100); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener); |  |  |  |         mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         String[] stringsForAmPm = new DateFormatSymbols().getAmPmStrings(); |  |  |  |         // 初始化AM/PM选择器
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         mAmPmSpinner = (NumberPicker) findViewById(R.id.amPm); |  |  |  |         mAmPmSpinner = findViewById(R.id.amPm); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         mAmPmSpinner.setMinValue(AMPM_SPINNER_MIN_VAL); |  |  |  |         mAmPmSpinner.setMinValue(AMPM_SPINNER_MIN_VAL); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mAmPmSpinner.setMaxValue(AMPM_SPINNER_MAX_VAL); |  |  |  |         mAmPmSpinner.setMaxValue(AMPM_SPINNER_MAX_VAL); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mAmPmSpinner.setDisplayedValues(stringsForAmPm); |  |  |  |          | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 本地化AM/PM符号
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         updateAmPmSymbols(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mAmPmSpinner.setOnValueChangedListener(mOnAmPmChangedListener); |  |  |  |         mAmPmSpinner.setOnValueChangedListener(mOnAmPmChangedListener); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // update controls to initial state
 |  |  |  |         // 更新UI控件
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         updateDateControl(); |  |  |  |         updateDateControl(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         updateHourControl(); |  |  |  |         updateHourControl(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         updateAmPmControl(); |  |  |  |         updateAmPmControl(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         set24HourView(is24HourView); |  |  |  |         // 设置初始时间
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         // set to current time
 |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         setCurrentDate(date); |  |  |  |         setCurrentDate(date); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 应用启用状态
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         setEnabled(isEnabled()); |  |  |  |         setEnabled(isEnabled()); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // set the content descriptions
 |  |  |  |         // 应用深色模式
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         mInitialising = false; |  |  |  |         applyDarkMode(); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 初始化完成
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mState = MODE_NORMAL; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /*************************** 公共方法 ***************************/ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     @Override |  |  |  |     @Override | 
			
		
	
		
		
			
				
					
					|  |  |  |     public void setEnabled(boolean enabled) { |  |  |  |     public void setEnabled(boolean enabled) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (mIsEnabled == enabled) { |  |  |  |         if (mIsEnabled == enabled) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             return; |  |  |  |             return; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         super.setEnabled(enabled); |  |  |  |         super.setEnabled(enabled); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 设置子控件状态
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         mDateSpinner.setEnabled(enabled); |  |  |  |         mDateSpinner.setEnabled(enabled); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mMinuteSpinner.setEnabled(enabled); |  |  |  |         mMinuteSpinner.setEnabled(enabled); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mHourSpinner.setEnabled(enabled); |  |  |  |         mHourSpinner.setEnabled(enabled); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mAmPmSpinner.setEnabled(enabled); |  |  |  |         mAmPmSpinner.setEnabled(enabled); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |         mIsEnabled = enabled; |  |  |  |         mIsEnabled = enabled; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -233,37 +269,37 @@ public class DateTimePicker extends FrameLayout { | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Get the current date in millis |  |  |  |      * 获取当前时间戳 (毫秒) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @return the current date in millis |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public long getCurrentDateInTimeMillis() { |  |  |  |     public long getCurrentDateInTimeMillis() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return mDate.getTimeInMillis(); |  |  |  |         return mDate.getTimeInMillis(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Set the current date |  |  |  |      * 设置当前时间 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param date The current date in millis |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public void setCurrentDate(long date) { |  |  |  |     public void setCurrentDate(long date) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 验证日期范围
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (date < mMinDate || date > mMaxDate) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Log.w(TAG, "设置日期超出范围: " + date); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             return; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |         Calendar cal = Calendar.getInstance(); |  |  |  |         Calendar cal = Calendar.getInstance(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         cal.setTimeInMillis(date); |  |  |  |         cal.setTimeInMillis(date); | 
			
		
	
		
		
			
				
					
					|  |  |  |         setCurrentDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), |  |  |  |         setCurrentDate( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)); |  |  |  |             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 |  |  |  |     public void setCurrentDate(int year, int month, int dayOfMonth, int hourOfDay, int minute) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * @param month The current month |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param dayOfMonth The current dayOfMonth |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param hourOfDay The current hourOfDay |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param minute The current minute |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     public void setCurrentDate(int year, int month, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             int dayOfMonth, int hourOfDay, int minute) { |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         setCurrentYear(year); |  |  |  |         setCurrentYear(year); | 
			
		
	
		
		
			
				
					
					|  |  |  |         setCurrentMonth(month); |  |  |  |         setCurrentMonth(month); | 
			
		
	
		
		
			
				
					
					|  |  |  |         setCurrentDay(dayOfMonth); |  |  |  |         setCurrentDay(dayOfMonth); | 
			
		
	
	
		
		
			
				
					|  |  | @ -272,21 +308,18 @@ public class DateTimePicker extends FrameLayout { | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Get current year |  |  |  |      * 获取当前年份 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @return The current year |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public int getCurrentYear() { |  |  |  |     public int getCurrentYear() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return mDate.get(Calendar.YEAR); |  |  |  |         return mDate.get(Calendar.YEAR); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Set current year |  |  |  |      * 设置当前年份 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param year The current year |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public void setCurrentYear(int year) { |  |  |  |     public void setCurrentYear(int year) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (!mInitialising && year == getCurrentYear()) { |  |  |  |         // 检查状态避免不必要的更新
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (mState != MODE_INITIALIZING && year == getCurrentYear()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             return; |  |  |  |             return; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         mDate.set(Calendar.YEAR, year); |  |  |  |         mDate.set(Calendar.YEAR, year); | 
			
		
	
	
		
		
			
				
					|  |  | @ -295,21 +328,17 @@ public class DateTimePicker extends FrameLayout { | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Get current month in the year |  |  |  |      * 获取当前月份 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @return The current month in the year |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public int getCurrentMonth() { |  |  |  |     public int getCurrentMonth() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return mDate.get(Calendar.MONTH); |  |  |  |         return mDate.get(Calendar.MONTH); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Set current month in the year |  |  |  |      * 设置当前月份 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param month The month in the year |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public void setCurrentMonth(int month) { |  |  |  |     public void setCurrentMonth(int month) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (!mInitialising && month == getCurrentMonth()) { |  |  |  |         if (mState != MODE_INITIALIZING && month == getCurrentMonth()) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             return; |  |  |  |             return; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         mDate.set(Calendar.MONTH, month); |  |  |  |         mDate.set(Calendar.MONTH, month); | 
			
		
	
	
		
		
			
				
					|  |  | @ -318,21 +347,17 @@ public class DateTimePicker extends FrameLayout { | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Get current day of the month |  |  |  |      * 获取当前日期 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @return The day of the month |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public int getCurrentDay() { |  |  |  |     public int getCurrentDay() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return mDate.get(Calendar.DAY_OF_MONTH); |  |  |  |         return mDate.get(Calendar.DAY_OF_MONTH); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Set current day of the month |  |  |  |      * 设置当前日期 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param dayOfMonth The day of the month |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public void setCurrentDay(int dayOfMonth) { |  |  |  |     public void setCurrentDay(int dayOfMonth) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (!mInitialising && dayOfMonth == getCurrentDay()) { |  |  |  |         if (mState != MODE_INITIALIZING && dayOfMonth == getCurrentDay()) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             return; |  |  |  |             return; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); |  |  |  |         mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); | 
			
		
	
	
		
		
			
				
					|  |  | @ -341,68 +366,66 @@ public class DateTimePicker extends FrameLayout { | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Get current hour in 24 hour mode, in the range (0~23) |  |  |  |      * 获取当前小时(24小时制) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * @return The current hour in 24 hour mode |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public int getCurrentHourOfDay() { |  |  |  |     public int getCurrentHourOfDay() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return mDate.get(Calendar.HOUR_OF_DAY); |  |  |  |         return mDate.get(Calendar.HOUR_OF_DAY); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     private int getCurrentHour() { |  |  |  |     /** | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         if (mIs24HourView){ |  |  |  |      * 根据显示模式获取小时 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             return getCurrentHourOfDay(); |  |  |  |      */ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         } else { |  |  |  |     private int getCurrentDisplayHour() { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         int hour = getCurrentHourOfDay(); |  |  |  |         int hour = getCurrentHourOfDay(); | 
			
		
	
		
		
			
				
					
					|  |  |  |             if (hour > HOURS_IN_HALF_DAY) { |  |  |  |         if (mIs24HourView) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 return hour - HOURS_IN_HALF_DAY; |  |  |  |             return hour; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         } else { |  |  |  |         } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |                 return hour == 0 ? HOURS_IN_HALF_DAY : hour; |  |  |  |             if (hour == 0 || hour == 12) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 return 12; | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             return hour % 12; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Set current hour in 24 hour mode, in the range (0~23) |  |  |  |      * 设置当前小时(24小时制) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param hourOfDay |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public void setCurrentHour(int hourOfDay) { |  |  |  |     public void setCurrentHour(int hourOfDay) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (!mInitialising && hourOfDay == getCurrentHourOfDay()) { |  |  |  |         // 验证小时值是否有效
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (hourOfDay < 0 || hourOfDay > 23) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Log.e(TAG, "无效的小时值: " + hourOfDay); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             return; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (mState != MODE_INITIALIZING && hourOfDay == getCurrentHourOfDay()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             return; |  |  |  |             return; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |         mDate.set(Calendar.HOUR_OF_DAY, hourOfDay); |  |  |  |         mDate.set(Calendar.HOUR_OF_DAY, hourOfDay); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 更新AM/PM状态
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (!mIs24HourView) { |  |  |  |         if (!mIs24HourView) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             if (hourOfDay >= HOURS_IN_HALF_DAY) { |  |  |  |             mIsAm = (hourOfDay < 12); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 mIsAm = false; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 if (hourOfDay > HOURS_IN_HALF_DAY) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     hourOfDay -= HOURS_IN_HALF_DAY; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             } else { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 mIsAm = true; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 if (hourOfDay == 0) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     hourOfDay = HOURS_IN_HALF_DAY; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             updateAmPmControl(); |  |  |  |             updateAmPmControl(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         mHourSpinner.setValue(hourOfDay); |  |  |  |          | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 更新显示值
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mHourSpinner.setValue(getCurrentDisplayHour()); | 
			
		
	
		
		
			
				
					
					|  |  |  |         onDateTimeChanged(); |  |  |  |         onDateTimeChanged(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Get currentMinute |  |  |  |      * 获取当前分钟 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @return The Current Minute |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public int getCurrentMinute() { |  |  |  |     public int getCurrentMinute() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return mDate.get(Calendar.MINUTE); |  |  |  |         return mDate.get(Calendar.MINUTE); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Set current minute |  |  |  |      * 设置当前分钟 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public void setCurrentMinute(int minute) { |  |  |  |     public void setCurrentMinute(int minute) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (!mInitialising && minute == getCurrentMinute()) { |  |  |  |         if (mState != MODE_INITIALIZING && minute == getCurrentMinute()) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             return; |  |  |  |             return; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         mMinuteSpinner.setValue(minute); |  |  |  |         mMinuteSpinner.setValue(minute); | 
			
		
	
	
		
		
			
				
					|  |  | @ -411,53 +434,148 @@ public class DateTimePicker extends FrameLayout { | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @return true if this is in 24 hour view else false. |  |  |  |      * 是否使用24小时制 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public boolean is24HourView () { |  |  |  |     public boolean is24HourView () { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return mIs24HourView; |  |  |  |         return mIs24HourView; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Set whether in 24 hour or AM/PM mode. |  |  |  |      * 设置24小时制模式 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param is24HourView True for 24 hour mode. False for AM/PM mode. |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public void set24HourView(boolean is24HourView) { |  |  |  |     public void set24HourView(boolean is24HourView) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (mIs24HourView == is24HourView) { |  |  |  |         if (mIs24HourView == is24HourView) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             return; |  |  |  |             return; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         mIs24HourView = is24HourView; |  |  |  |         mIs24HourView = is24HourView; | 
			
		
	
		
		
			
				
					
					|  |  |  |         mAmPmSpinner.setVisibility(is24HourView ? View.GONE : View.VISIBLE); |  |  |  |          | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         int hour = getCurrentHourOfDay(); |  |  |  |         // 更新AM/PM显示
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         int amPmVisibility = is24HourView ? View.GONE : View.VISIBLE; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mAmPmSpinner.setVisibility(amPmVisibility); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 更新小时控制
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         updateHourControl(); |  |  |  |         updateHourControl(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         setCurrentHour(hour); |  |  |  |         setCurrentHour(getCurrentHourOfDay()); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         updateAmPmControl(); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 设置最小可选日期 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public void setMinDate(long minDate) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mMinDate = minDate; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         validateCurrentDate(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 设置最大可选日期 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public void setMaxDate(long maxDate) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mMaxDate = maxDate; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         validateCurrentDate(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 设置日期时间变更监听器 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public void setOnDateTimeChangedListener(OnDateTimeChangedListener listener) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mOnDateTimeChangedListener = listener; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /*************************** 私有方法 ***************************/ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 计算新小时值 (处理滚动越界) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private int computeNewHour(int oldVal, int newVal) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         int currentHour = getCurrentHourOfDay(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (mIs24HourView) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             // 24小时制处理
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (oldVal == HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW && newVal == 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 return 0; // 23 -> 0
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } else if (oldVal == 0 && newVal == HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 return 23; // 0 -> 23
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             // 12小时制处理
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (oldVal == 12 && newVal == 11) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 return mIsAm ? 11 : 23; // PM状态下12->11实际上是23点
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } else if (oldVal == 11 && newVal == 12) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 return mIsAm ? 12 : 0; // AM状态下11->12是中午12点
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 基本转换
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         int hour = newVal; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (!mIs24HourView && !mIsAm && hour != 12) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             hour += 12; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 特殊处理中午12点
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (hour == 24) hour = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return hour; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 更新日期控件显示 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     private void updateDateControl() { |  |  |  |     private void updateDateControl() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         Calendar cal = Calendar.getInstance(); |  |  |  |         Calendar cal = Calendar.getInstance(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         cal.setTimeInMillis(mDate.getTimeInMillis()); |  |  |  |         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, -DAYS_IN_ALL_WEEK / 2); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         for (int i = 0; i < DAYS_IN_ALL_WEEK; i++) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             // 生成日期显示字符串 (带星期)
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             mDateDisplayValues[i] = formatDateWithWeekday(cal); | 
			
		
	
		
		
			
				
					
					|  |  |  |             cal.add(Calendar.DAY_OF_YEAR, 1); |  |  |  |             cal.add(Calendar.DAY_OF_YEAR, 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |             mDateDisplayValues[i] = (String) DateFormat.format("MM.dd EEEE", cal); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 设置日期选择器显示内容
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         mDateSpinner.setDisplayedValues(mDateDisplayValues); |  |  |  |         mDateSpinner.setDisplayedValues(mDateDisplayValues); | 
			
		
	
		
		
			
				
					
					|  |  |  |         mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2); |  |  |  |         mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2); // 当前日期在中间位置
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         mDateSpinner.invalidate(); |  |  |  |     } | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 格式化日期 (带星期显示) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private String formatDateWithWeekday(Calendar calendar) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         java.text.DateFormat dateFormat = java.text.DateFormat.getDateInstance( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             java.text.DateFormat.MEDIUM, Locale.getDefault()); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 添加星期显示
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         String weekday = getWeekdayName(calendar.get(Calendar.DAY_OF_WEEK)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return String.format("%s (%s)",  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             dateFormat.format(calendar.getTime()), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             weekday | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 获取本地化星期名称 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private String getWeekdayName(int dayOfWeek) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         String[] weekdays = new DateFormatSymbols().getWeekdays(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (dayOfWeek >= Calendar.SUNDAY && dayOfWeek <= Calendar.SATURDAY) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             return weekdays[dayOfWeek]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return ""; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 更新AM/PM控件 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     private void updateAmPmControl() { |  |  |  |     private void updateAmPmControl() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (mIs24HourView) { |  |  |  |         if (mIs24HourView) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             mAmPmSpinner.setVisibility(View.GONE); |  |  |  |             return; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         } else { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             int index = mIsAm ? Calendar.AM : Calendar.PM; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             mAmPmSpinner.setValue(index); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             mAmPmSpinner.setVisibility(View.VISIBLE); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mAmPmSpinner.setValue(mIsAm ? 0 : 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 更新小时控件范围 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     private void updateHourControl() { |  |  |  |     private void updateHourControl() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (mIs24HourView) { |  |  |  |         if (mIs24HourView) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW); |  |  |  |             mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW); | 
			
		
	
	
		
		
			
				
					|  |  | @ -466,20 +584,101 @@ public class DateTimePicker extends FrameLayout { | 
			
		
	
		
		
			
				
					
					|  |  |  |             mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW); |  |  |  |             mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW); | 
			
		
	
		
		
			
				
					
					|  |  |  |             mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW); |  |  |  |             mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW); | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mHourSpinner.setValue(getCurrentDisplayHour()); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Set the callback that indicates the 'Set' button has been pressed. |  |  |  |      * 更新AM/PM符号 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * @param callback the callback, if null will do nothing |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public void setOnDateTimeChangedListener(OnDateTimeChangedListener callback) { |  |  |  |     private void updateAmPmSymbols() { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         mOnDateTimeChangedListener = callback; |  |  |  |         String[] ampmSymbols = new DateFormatSymbols().getAmPmStrings(); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (ampmSymbols.length < 2) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Log.e(TAG, "AM/PM符号获取失败"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             ampmSymbols = new String[]{"AM", "PM"}; // 默认值
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         mAmPmSpinner.setDisplayedValues(ampmSymbols); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 应用深色模式适配 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private void applyDarkMode() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 在Android 10+系统上添加深色模式支持
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             setForceDarkAllowed(true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 验证当前日期是否在允许范围内 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private void validateCurrentDate() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         long currentTime = getCurrentDateInTimeMillis(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (currentTime < mMinDate || currentTime > mMaxDate) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             // 自动调整到有效范围
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             long newTime = Math.max(mMinDate, Math.min(currentTime, mMaxDate)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             setCurrentDate(newTime); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |              | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             // 触发更新
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             updateDateControl(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             updateHourControl(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             updateAmPmControl(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 检查当前日期是否在允许范围内 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private boolean isDateInRange() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         long currentTime = mDate.getTimeInMillis(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return currentTime >= mMinDate && currentTime <= mMaxDate; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 回滚日期变化 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private void revertDateChange() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // 回滚到上一次有效日期
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (mDateSpinner.getValue() > DAYS_IN_ALL_WEEK / 2) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             mDateSpinner.setValue(mDateSpinner.getValue() - 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } else if (mDateSpinner.getValue() < DAYS_IN_ALL_WEEK / 2) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             mDateSpinner.setValue(mDateSpinner.getValue() + 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 显示日期范围警告 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private void showDateRangeWarning() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         Context context = getContext(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         Calendar minCal = Calendar.getInstance(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         minCal.setTimeInMillis(mMinDate); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         Calendar maxCal = Calendar.getInstance(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         maxCal.setTimeInMillis(mMaxDate); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         java.text.DateFormat df = java.text.DateFormat.getDateInstance(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         String msg = String.format( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             context.getString(R.string.date_range_warning), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             df.format(minCal.getTime()), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             df.format(maxCal.getTime()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * 触发日期时间变更事件 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     private void onDateTimeChanged() { |  |  |  |     private void onDateTimeChanged() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (mOnDateTimeChangedListener != null) { |  |  |  |         if (mOnDateTimeChangedListener != null) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             mOnDateTimeChangedListener.onDateTimeChanged(this, getCurrentYear(), |  |  |  |             mOnDateTimeChangedListener.onDateTimeChanged( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                     getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute()); |  |  |  |                 this, | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 getCurrentYear(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 getCurrentMonth(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 getCurrentDay(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 getCurrentHourOfDay(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 getCurrentMinute() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             ); | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } |