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.

455 lines
17 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.

// 声明版权信息表明该文件由MiCode开源社区在2010-2011年间编写并遵循Apache License 2.0许可协议
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// 导入所需的包和类
package net.micode.notes.ui; // 指定该类所在的包名
import java.text.DateFormatSymbols; // 导入DateFormatSymbols类用于获取日期格式符号
import java.util.Calendar; // 导入Calendar类用于日期和时间操作
import net.micode.notes.R; // 导入应用程序的资源文件
import android.content.Context; // 导入Context类用于获取应用程序上下文
import android.text.format.DateFormat; // 导入DateFormat类用于日期格式化
import android.view.View; // 导入View类用于视图操作
import android.widget.FrameLayout; // 导入FrameLayout类用于布局
import android.widget.NumberPicker; // 导入NumberPicker类用于数字选择器
// 定义DateTimePicker类继承自FrameLayout类
public class DateTimePicker extends FrameLayout {
// 定义常量
private static final boolean DEFAULT_ENABLE_STATE = true; // 默认启用状态
private static final int HOURS_IN_HALF_DAY = 12; // 半天的小时数
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; // 日期选择器的最大值
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; // 24小时视图的小时选择器最大值
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; // 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; // 是否为上午
private boolean mIs24HourView; // 是否为24小时视图
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) {
// 处理分钟更改逻辑
int minValue = mMinuteSpinner.getMinValue();
int maxValue = mMinuteSpinner.getMaxValue();
int offset = 0;
if (oldVal == maxValue && newVal == minValue) {
offset += 1;
} else if (oldVal == minValue && newVal == maxValue) {
offset -= 1;
}
if (offset != 0) {
// 更新日期和小时
mDate.add(Calendar.HOUR_OF_DAY, offset);
mHourSpinner.setValue(getCurrentHour());
updateDateControl();
int newHour = getCurrentHourOfDay();
if (newHour >= HOURS_IN_HALF_DAY) {
mIsAm = false;
updateAmPmControl();
} else {
mIsAm = true;
updateAmPmControl();
}
}
// 更新分钟
mDate.set(Calendar.MINUTE, newVal);
onDateTimeChanged();
}
};
// 定义上午/下午更改监听器
private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
// 切换上午/下午状态
mIsAm = !mIsAm;
if (mIsAm) {
mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY);
} else {
mDate.add(Calendar.HOUR_OF_DAY, HOURS_IN_HALF_DAY);
}
updateAmPmControl();
onDateTimeChanged();
}
};
// 定义日期时间更改监听器接口
public interface OnDateTimeChangedListener {
void onDateTimeChanged(DateTimePicker view, int year, int month,
int dayOfMonth, int hourOfDay, int minute);
}
// 构造函数初始化DateTimePicker
public DateTimePicker(Context context) {
this(context, System.currentTimeMillis());
}
// 构造函数初始化DateTimePicker并设置日期
public DateTimePicker(Context context, long date) {
this(context, date, DateFormat.is24HourFormat(context));
}
// 构造函数初始化DateTimePicker并设置日期和24小时视图状态
public DateTimePicker(Context context, long date, boolean is24HourView) {
super(context);
mDate = Calendar.getInstance();
mInitialising = true;
mIsAm = getCurrentHourOfDay() >= HOURS_IN_HALF_DAY;
inflate(context, R.layout.datetime_picker, this);
// 初始化日期选择器
mDateSpinner = (NumberPicker) findViewById(R.id.date);
mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL);
mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL);
mDateSpinner.setOnValueChangedListener(mOnDateChangedListener);
// 初始化小时选择器
mHourSpinner = (NumberPicker) findViewById(R.id.hour);
mHourSpinner.setOnValueChangedListener(mOnHourChangedListener);
// 初始化分钟选择器
mMinuteSpinner = (NumberPicker) findViewById(R.id.minute);
mMinuteSpinner.setMinValue(MINUT_SPINNER_MIN_VAL);
mMinuteSpinner.setMaxValue(MINUT_SPINNER_MAX_VAL);
mMinuteSpinner.setOnLongPressUpdateInterval(100);
mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener);
// 初始化上午/下午选择器
String[] stringsForAmPm = new DateFormatSymbols().getAmPmStrings();
mAmPmSpinner = (NumberPicker) findViewById(R.id.amPm);
mAmPmSpinner.setMinValue(AMPM_SPINNER_MIN_VAL);
mAmPmSpinner.setMaxValue(AMPM_SPINNER_MAX_VAL);
mAmPmSpinner.setDisplayedValues(stringsForAmPm);
mAmPmSpinner.setOnValueChangedListener(mOnAmPmChangedListener);
// 更新控件到初始状态
updateDateControl();
updateHourControl();
updateAmPmControl();
// 设置24小时视图状态
set24HourView(is24HourView);
// 设置当前日期
setCurrentDate(date);
// 设置启用状态
setEnabled(isEnabled());
// 设置内容描述
mInitialising = false;
}
// 重写setEnabled方法设置控件的启用状态
@Override
public void setEnabled(boolean enabled) {
if (mIsEnabled == enabled) {
return;
}
super.setEnabled(enabled);
mDateSpinner.setEnabled(enabled);
mMinuteSpinner.setEnabled(enabled);
mHourSpinner.setEnabled(enabled);
mAmPmSpinner.setEnabled(enabled);
mIsEnabled = enabled;
}
// 获取控件的启用状态
@Override
public boolean isEnabled() {
return mIsEnabled;
}
// 获取当前日期的时间戳
public long getCurrentDateInTimeMillis() {
return mDate.getTimeInMillis();
}
// 设置当前日期
public void setCurrentDate(long date) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(date);
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));
}
// 设置当前日期
public void setCurrentDate(int year, int month,
int dayOfMonth, int hourOfDay, int minute) {
setCurrentYear(year);
setCurrentMonth(month);
setCurrentDay(dayOfMonth);
setCurrentHour(hourOfDay);
setCurrentMinute(minute);
}
// 获取当前年份
public int getCurrentYear() {
return mDate.get(Calendar.YEAR);
}
// 设置当前年份
public void setCurrentYear(int year) {
if (!mInitialising && year == getCurrentYear()) {
return;
}
mDate.set(Calendar.YEAR, year);
updateDateControl();
onDateTimeChanged();
}
// 获取当前月份
public int getCurrentMonth() {
return mDate.get(Calendar.MONTH);
}
// 设置当前月份
public void setCurrentMonth(int month) {
if (!mInitialising && month == getCurrentMonth()) {
return;
}
mDate.set(Calendar.MONTH, month);
updateDateControl();
onDateTimeChanged();
}
// 获取当前天数
public int getCurrentDay() {
return mDate.get(Calendar.DAY_OF_MONTH);
}
// 设置当前天数
public void setCurrentDay(int dayOfMonth) {
if (!mInitialising && dayOfMonth == getCurrentDay()) {
return;
}
mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
updateDateControl();
onDateTimeChanged();
}
// 获取当前小时24小时制
public int getCurrentHourOfDay() {
return mDate.get(Calendar.HOUR_OF_DAY);
}
// 获取当前小时根据24小时视图状态
private int getCurrentHour() {
if (mIs24HourView){
return getCurrentHourOfDay();
} else {
int hour = getCurrentHourOfDay();
if (hour > HOURS_IN_HALF_DAY) {
return hour - HOURS_IN_HALF_DAY;
} else {
return hour == 0 ? HOURS_IN_HALF_DAY : hour;
}
}
}
// 设置当前小时24小时制
public void setCurrentHour(int hourOfDay) {
if (!mInitialising && hourOfDay == getCurrentHourOfDay()) {
return;
}
mDate.set(Calendar.HOUR_OF_DAY, hourOfDay);
if (!mIs24HourView) {
if (hourOfDay >= HOURS_IN_HALF_DAY) {
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();
}
mHourSpinner.setValue(hourOfDay);
onDateTimeChanged();
}
// 获取当前分钟
public int getCurrentMinute() {
return mDate.get(Calendar.MINUTE);
}
// 设置当前分钟
public void setCurrentMinute(int minute) {
if (!mInitialising && minute == getCurrentMinute()) {
return;
}
mMinuteSpinner.setValue(minute);
mDate.set(Calendar.MINUTE, minute);
onDateTimeChanged();
}
// 获取是否为24小时视图
public boolean is24HourView () {
return mIs24HourView;
}
// 设置是否为24小时视图
public void set24HourView(boolean is24HourView) {
if (mIs24HourView == is24HourView) {
return;
}
mIs24HourView = is24HourView;
mAmPmSpinner.setVisibility(is24HourView ? View.GONE : View.VISIBLE);
int hour = getCurrentHourOfDay();
updateHourControl();
setCurrentHour(hour);
updateAmPmControl();
}
// 更新日期控件
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();
}
// 更新上午/下午控件
private void updateAmPmControl() {
if (mIs24HourView) {
mAmPmSpinner.setVisibility(View.GONE);
} else {
int index = mIsAm ? Calendar.AM : Calendar.PM;
mAmPmSpinner.setValue(index);
mAmPmSpinner.setVisibility(View.VISIBLE);
}
}
// 更新小时控件
private void updateHourControl() {
if (mIs24HourView) {
mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW);
mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW);
} else {
mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW);
mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW);
}
}
// 设置日期时间更改监听器
public void setOnDateTimeChangedListener(OnDateTimeChangedListener callback) {
mOnDateTimeChangedListener = callback;
}
// 触发日期时间更改事件
private void onDateTimeChanged() {
if (mOnDateTimeChangedListener != null) {
mOnDateTimeChangedListener.onDateTimeChanged(this, getCurrentYear(),
getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute());
}
}