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.
GPL_Project/doc/标注/210340062_刘瑞轩/DateTimePicker.java

490 lines
19 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.

/*
* 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;
import java.util.Calendar;
import net.micode.notes.R;
import android.content.Context;
import android.text.format.DateFormat;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.NumberPicker;
/*
Author:刘瑞轩
Data:2023/4/12
*/
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;
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_MAX_VAL_12_HOUR_VIEW = 12;
private static final int MINUT_SPINNER_MIN_VAL = 0;
private static final int MINUT_SPINNER_MAX_VAL = 59;
private static final int AMPM_SPINNER_MIN_VAL = 0;
private static final int AMPM_SPINNER_MAX_VAL = 1;
private final NumberPicker mDateSpinner;
private final NumberPicker mHourSpinner;
private final NumberPicker mMinuteSpinner;
private final NumberPicker mAmPmSpinner;
private Calendar mDate;
private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK];
private boolean mIsAm;
private boolean mIs24HourView;
private boolean mIsEnabled = DEFAULT_ENABLE_STATE;
private boolean mInitialising;
private OnDateTimeChangedListener mOnDateTimeChangedListener;
private NumberPicker.OnValueChangeListener mOnDateChangedListener = new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {//更改日期
mDate.add(Calendar.DAY_OF_YEAR, newVal - oldVal);
updateDateControl();
onDateTimeChanged();
}
};//当用户更改值之后改变便签的修改日期
private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {//各自的参数代表被改变值得NumberPicker对象旧值新值
boolean isDateChanged = false;//用户是否改变值
Calendar cal = Calendar.getInstance();//获取当前的时间
if (!mIs24HourView) {//不是用的24小时制度
if (!mIsAm && oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) {//是下午旧值是11新值是12代表到了下一天
cal.setTimeInMillis(mDate.getTimeInMillis());//将修改时间修改为当前的时间
cal.add(Calendar.DAY_OF_YEAR, 1);//过了一天将日期加1
isDateChanged = true;
} else if (mIsAm && oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) {//如果当前是上午,并且
//旧值是12新值是11那么就代表回到了上一天
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) {//只要之前是11现在是12或者是之前是12现在是11AM和PM都会发生改变取反
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);
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) {//如果新的是最小的旧的值是最大的那么小时加1
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);//如果是下午变成上午那么需要减去12小时
} else {
mDate.add(Calendar.HOUR_OF_DAY, HOURS_IN_HALF_DAY);//如果是上午变成下午那么需要加上12小时
}
updateAmPmControl();
onDateTimeChanged();
}
};
public interface OnDateTimeChangedListener {
void onDateTimeChanged(DateTimePicker view, int year, int month,
int dayOfMonth, int hourOfDay, int minute);
}
public DateTimePicker(Context context) {
this(context, System.currentTimeMillis());
}
public DateTimePicker(Context context, long date) {
this(context, date, DateFormat.is24HourFormat(context));
}
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);//设置按下更新的间隔是100ms
mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener);//设置分钟监听器
String[] stringsForAmPm = new DateFormatSymbols().getAmPmStrings();//获取当前设备上的AM/PM字符串数组第一个元素为AM第二个元素为PM
mAmPmSpinner = (NumberPicker) findViewById(R.id.amPm);
mAmPmSpinner.setMinValue(AMPM_SPINNER_MIN_VAL);
mAmPmSpinner.setMaxValue(AMPM_SPINNER_MAX_VAL);
mAmPmSpinner.setDisplayedValues(stringsForAmPm);
mAmPmSpinner.setOnValueChangedListener(mOnAmPmChangedListener);//设置上午下午监听器
// update controls to initial state
updateDateControl();//更新限制
updateHourControl();
updateAmPmControl();
set24HourView(is24HourView);
// set to current time
setCurrentDate(date);
setEnabled(isEnabled());
// set the content descriptions
mInitialising = false;
}
@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;
}//返回是否可用
/**
* Get the current date in millis
*
* @return the current date in millis
*/
public long getCurrentDateInTimeMillis() {
return mDate.getTimeInMillis();
}//获取当前的日期
/**
* Set the current date
*
* @param date The current date in millis
*/
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));
}
/**
* Set the current date
*
* @param year The current year
* @param month The current month
* @param dayOfMonth The current dayOfMonth
* @param hourOfDay The current hourOfDay
* @param minute The current minute
*/
public void setCurrentDate(int year, int month,
int dayOfMonth, int hourOfDay, int minute) {
setCurrentYear(year);
setCurrentMonth(month);
setCurrentDay(dayOfMonth);
setCurrentHour(hourOfDay);
setCurrentMinute(minute);
}//设置时间
/**
* Get current year
*
* @return The current year
*/
public int getCurrentYear() {
return mDate.get(Calendar.YEAR);
}//返回当前年
/**
* Set current year
*
* @param year The current year
*/
public void setCurrentYear(int year) {
if (!mInitialising && year == getCurrentYear()) {//如果已经初始化并且年份和当前的相同
return;
}
mDate.set(Calendar.YEAR, year);//更新
updateDateControl();
onDateTimeChanged();
}
/**
* Get current month in the year
*
* @return The current month in the year
*/
public int getCurrentMonth() {
return mDate.get(Calendar.MONTH);
}//获得月份
/**
* Set current month in the year
*
* @param month The month in the year
*/
public void setCurrentMonth(int month) {
if (!mInitialising && month == getCurrentMonth()) {
return;
}
mDate.set(Calendar.MONTH, month);//更新月份
updateDateControl();
onDateTimeChanged();
}
/**
* Get current day of the month
*
* @return The day of the month
*/
public int getCurrentDay() {
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) {//更新天
if (!mInitialising && dayOfMonth == getCurrentDay()) {
return;
}
mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
updateDateControl();
onDateTimeChanged();
}
/**
* Get current hour in 24 hour mode, in the range (0~23)
* @return The current hour in 24 hour mode
*/
public int getCurrentHourOfDay() {
return mDate.get(Calendar.HOUR_OF_DAY);
}//获取当前的小时
private int getCurrentHour() {
if (mIs24HourView){//如果是24小时
return getCurrentHourOfDay();
} else {
int hour = getCurrentHourOfDay();//获取小时
if (hour > HOURS_IN_HALF_DAY) {//如果大于12应该减去12
return hour - HOURS_IN_HALF_DAY;
} else {
return hour == 0 ? HOURS_IN_HALF_DAY : hour;//否则就和当前的相同
}
}
}
/**
* Set current hour in 24 hour mode, in the range (0~23)
*
* @param hourOfDay
*/
public void setCurrentHour(int hourOfDay) {
if (!mInitialising && hourOfDay == getCurrentHourOfDay()) {//如果已经初始化并且和现在的小时一样就不用管
return;
}
mDate.set(Calendar.HOUR_OF_DAY, hourOfDay);//设置小时
if (!mIs24HourView) {//如果不是24小时制度
if (hourOfDay >= HOURS_IN_HALF_DAY) {
mIsAm = false;//代表是下午
if (hourOfDay > HOURS_IN_HALF_DAY) {//如果大于12
hourOfDay -= HOURS_IN_HALF_DAY;
}
} else {
mIsAm = true;//时上午
if (hourOfDay == 0) {
hourOfDay = HOURS_IN_HALF_DAY;//代表到达了最后
}
}
updateAmPmControl();
}
mHourSpinner.setValue(hourOfDay);//更新时间
onDateTimeChanged();
}
/**
* Get currentMinute
*
* @return The Current Minute
*/
public int getCurrentMinute() {
return mDate.get(Calendar.MINUTE);
}
/**
* Set current minute
*/
public void setCurrentMinute(int minute) {
if (!mInitialising && minute == getCurrentMinute()) {
return;
}
mMinuteSpinner.setValue(minute);//设置时间
mDate.set(Calendar.MINUTE, minute);//设置分钟
onDateTimeChanged();
}
/**
* @return true if this is in 24 hour view else false.
*/
public boolean is24HourView () {
return mIs24HourView;
}//返回是否是24小时制
/**
* Set whether in 24 hour or AM/PM mode.
*
* @param is24HourView True for 24 hour mode. False for AM/PM mode.
*/
public void set24HourView(boolean is24HourView) {
if (mIs24HourView == is24HourView) {//如果是24小时制就无需更改
return;
}
mIs24HourView = is24HourView;//更改为24小时制度
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);//清空mDateSpinner显示的数据
for (int i = 0; i < DAYS_IN_ALL_WEEK; ++i) {
cal.add(Calendar.DAY_OF_YEAR, 1);//将当前的cal的最后一个数据加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) {//如果是24小时制
mAmPmSpinner.setVisibility(View.GONE);//上午下午不显示
} else {
int index = mIsAm ? Calendar.AM : Calendar.PM;//显示是上午还是下午
mAmPmSpinner.setValue(index);//显示对应的内容
mAmPmSpinner.setVisibility(View.VISIBLE);//可见
}
}
private void updateHourControl() {
if (mIs24HourView) {//如果是24小时制
mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW);//显示24小时最小值
mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW);//显示24小时最大值
} else {
mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW);//显示12小时最小值
mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW);//显示12小时最大值
}
}
/**
* Set the callback that indicates the 'Set' button has been pressed.
* @param callback the callback, if null will do nothing
*/
public void setOnDateTimeChangedListener(OnDateTimeChangedListener callback) {
mOnDateTimeChangedListener = callback;
}
private void onDateTimeChanged() {//更改便签时间
if (mOnDateTimeChangedListener != null) {
mOnDateTimeChangedListener.onDateTimeChanged(this, getCurrentYear(),
getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute());
}
}
}