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.
pyx_gitpractice/ui/DateTimePicker.java

412 lines
15 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 net.micode.notes.ui.DateTimePicker.OnDateTimeChangedListener;
import android.content.Context;
import android.text.format.DateFormat;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.NumberPicker;
public class DateTimePicker extends FrameLayout {
private static final boolean DEFAULT_ENABLE_STATE = true;
private static final int HOURS_IN_HALF_DAY = 12;
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 void removeSyncAccount() {
// 获取指定名称的 SharedPreferences 对象,使用私有模式,确保只有本应用可以访问这些设置
SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
// 获取 SharedPreferences 的编辑器,用于修改存储的设置
SharedPreferences.Editor editor = settings.edit();
// 检查 SharedPreferences 中是否包含同步账户名称的键
if (settings.contains(PREFERENCE_SYNC_ACCOUNT_NAME)) {
// 如果包含,则从编辑器中移除该键值对
editor.remove(PREFERENCE_SYNC_ACCOUNT_NAME);
}
// 检查 SharedPreferences 中是否包含最后同步时间的键
if (settings.contains(PREFERENCE_LAST_SYNC_TIME)) {
// 如果包含,则从编辑器中移除该键值对
editor.remove(PREFERENCE_LAST_SYNC_TIME);
}
// 提交编辑器中的修改,将更改保存到 SharedPreferences 中
editor.commit();
// 清理本地与 Google 任务GTask相关的信息由于数据库操作可能会阻塞主线程因此在新线程中执行
new Thread(new Runnable() {
public void run() {
// 创建一个 ContentValues 对象,用于存储要更新的数据
ContentValues values = new ContentValues();
// 将 GTask ID 字段设置为空字符串
values.put(NoteColumns.GTASK_ID, "");
// 将同步 ID 字段设置为 0
values.put(NoteColumns.SYNC_ID, 0);
// 使用 ContentResolver 更新 Notes 内容提供者中的笔记数据,将 GTask ID 和同步 ID 字段清空
getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null);
}
}).start();
}
// 获取当前设置的同步账户名称
public static String getSyncAccountName(Context context) {
// 获取指定名称的 SharedPreferences 对象,使用私有模式
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
// 从 SharedPreferences 中获取同步账户名称,如果不存在则返回空字符串
return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
}
// 设置最后一次同步的时间
public static void setLastSyncTime(Context context, long time) {
// 获取指定名称的 SharedPreferences 对象,使用私有模式
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
// 获取 SharedPreferences 的编辑器,用于修改存储的设置
SharedPreferences.Editor editor = settings.edit();
// 将最后同步时间存储到编辑器中
editor.putLong(PREFERENCE_LAST_SYNC_TIME, time);
// 提交编辑器中的修改,将更改保存到 SharedPreferences 中
editor.commit();
}
// 获取最后一次同步的时间
public static long getLastSyncTime(Context context) {
// 获取指定名称的 SharedPreferences 对象,使用私有模式
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
// 从 SharedPreferences 中获取最后同步时间,如果不存在则返回 0
return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0);
}
// 自定义广播接收器,用于接收 GTask 同步服务的广播
private class GTaskReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 刷新界面,更新账户设置和同步按钮状态等信息
refreshUI();
// 检查广播意图中是否包含正在同步的标志,并且标志为 true
if (intent.getBooleanExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_IS_SYNCING, false)) {
// 查找用于显示同步状态的 TextView 控件
TextView syncStatus = (TextView) findViewById(R.id.prefenerece_sync_status_textview);
// 设置同步状态文本为广播意图中携带的进度消息
syncStatus.setText(intent
.getStringExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_PROGRESS_MSG));
}
}
}
// 处理选项菜单的点击事件
public boolean onOptionsItemSelected(MenuItem item) {
// 根据点击的菜单项 ID 进行不同的处理
switch (item.getItemId()) {
// 如果点击的是应用图标(即返回按钮)
case android.R.id.home:
// 创建一个意图,用于启动 NotesListActivity
Intent intent = new Intent(this, NotesListActivity.class);
// 添加标志,确保启动的 NotesListActivity 位于任务栈的顶部,并清除之前的所有活动
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// 启动 NotesListActivity
startActivity(intent);
// 返回 true 表示事件已处理
return true;
// 如果点击的是其他菜单项
default:
// 返回 false 表示事件未处理
return false;
}
}
// 获取当前月份
public int getCurrentMonth() {
// 通过Calendar对象获取当前月份
return mDate.get(Calendar.MONTH);
}
/**
* 设置当前年份中的月份
*
* @param month 年份中的月份
*/
public void setCurrentMonth(int month) {
// 如果不是初始化阶段且设置的月份与当前月份相同,则直接返回
if (!mInitialising && month == getCurrentMonth()) {
return;
}
// 设置Calendar对象的月份
mDate.set(Calendar.MONTH, month);
// 更新日期控件显示
updateDateControl();
// 触发日期时间改变的回调
onDateTimeChanged();
}
/**
* 获取当前月份中的日期
*
* @return 月份中的日期
*/
public int getCurrentDay() {
// 通过Calendar对象获取当前月份中的日期
return mDate.get(Calendar.DAY_OF_MONTH);
}
/**
* 设置当前月份中的日期
*
* @param dayOfMonth 月份中的日期
*/
public void setCurrentDay(int dayOfMonth) {
// 如果不是初始化阶段且设置的日期与当前日期相同,则直接返回
if (!mInitialising && dayOfMonth == getCurrentDay()) {
return;
}
// 设置Calendar对象的日期
mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
// 更新日期控件显示
updateDateControl();
// 触发日期时间改变的回调
onDateTimeChanged();
}
/**
* 获取24小时制的当前小时范围在(0~23)
* @return 24小时制的当前小时
*/
public int getCurrentHourOfDay() {
// 通过Calendar对象获取24小时制的当前小时
return mDate.get(Calendar.HOUR_OF_DAY);
}
// 获取当前小时根据是否为24小时制进行不同处理
private int getCurrentHour() {
if (mIs24HourView){
// 如果是24小时制直接返回24小时制的当前小时
return getCurrentHourOfDay();
} else {
// 如果是12小时制
int hour = getCurrentHourOfDay();
if (hour > HOURS_IN_HALF_DAY) {
// 如果小时数大于12减去12
return hour - HOURS_IN_HALF_DAY;
} else {
// 如果小时数为0则显示为12否则直接显示
return hour == 0 ? HOURS_IN_HALF_DAY : hour;
}
}
}
/**
* 设置24小时制的当前小时范围在(0~23)
*
* @param hourOfDay 24小时制的当前小时
*/
public void setCurrentHour(int hourOfDay) {
// 如果不是初始化阶段且设置的小时与当前小时相同,则直接返回
if (!mInitialising && hourOfDay == getCurrentHourOfDay()) {
return;
}
// 设置Calendar对象的小时
mDate.set(Calendar.HOUR_OF_DAY, hourOfDay);
if (!mIs24HourView) {
// 如果是12小时制
if (hourOfDay >= HOURS_IN_HALF_DAY) {
// 如果小时数大于等于12设置为下午
mIsAm = false;
if (hourOfDay > HOURS_IN_HALF_DAY) {
// 如果小时数大于12减去12
hourOfDay -= HOURS_IN_HALF_DAY;
}
} else {
// 如果小时数小于12设置为上午
mIsAm = true;
if (hourOfDay == 0) {
// 如果小时数为0则显示为12
hourOfDay = HOURS_IN_HALF_DAY;
}
}
// 更新上午/下午控件显示
updateAmPmControl();
}
// 设置小时选择器的值
mHourSpinner.setValue(hourOfDay);
// 触发日期时间改变的回调
onDateTimeChanged();
}
/**
* 获取当前分钟
*
* @return 当前分钟
*/
public int getCurrentMinute() {
// 通过Calendar对象获取当前分钟
return mDate.get(Calendar.MINUTE);
}
/**
* 设置当前分钟
*/
public void setCurrentMinute(int minute) {
// 如果不是初始化阶段且设置的分钟与当前分钟相同,则直接返回
if (!mInitialising && minute == getCurrentMinute()) {
return;
}
// 设置分钟选择器的值
mMinuteSpinner.setValue(minute);
// 设置Calendar对象的分钟
mDate.set(Calendar.MINUTE, minute);
// 触发日期时间改变的回调
onDateTimeChanged();
}
/**
* @return 如果是24小时制视图返回true否则返回false。
*/
public boolean is24HourView () {
// 返回是否为24小时制视图的标志
return mIs24HourView;
}
/**
* 设置是否为24小时制或上午/下午模式。
*
* @param is24HourView 为true表示24小时制模式为false表示上午/下午模式。
*/
public void set24HourView(boolean is24HourView) {
// 如果当前模式与要设置的模式相同,则直接返回
if (mIs24HourView == is24HourView) {
return;
}
// 更新是否为24小时制视图的标志
mIs24HourView = is24HourView;
// 根据是否为24小时制视图显示或隐藏上午/下午选择器
mAmPmSpinner.setVisibility(is24HourView ? View.GONE : View.VISIBLE);
// 获取当前24小时制的小时
int hour = getCurrentHourOfDay();
// 更新小时选择器的范围
updateHourControl();
// 设置当前小时
setCurrentHour(hour);
// 更新上午/下午控件显示
updateAmPmControl();
}
// 更新日期控件的显示
private void updateDateControl() {
// 创建一个新的Calendar对象
Calendar cal = Calendar.getInstance();
// 设置Calendar对象的时间为当前时间
cal.setTimeInMillis(mDate.getTimeInMillis());
// 将日期向前移动DAYS_IN_ALL_WEEK / 2 + 1天
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) {
// 日期向后移动1天
cal.add(Calendar.DAY_OF_YEAR, 1);
// 将日期格式化为"MM.dd EEEE"的字符串
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 {
// 如果是12小时制视图根据是否为上午设置选择器的值
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);
mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW);
} else {
// 如果是12小时制视图设置小时选择器的最小值和最大值
mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW);
mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW);
}
}
/**
* 设置当点击“设置”按钮时的回调函数
* @param callback 回调函数如果为null则不做任何操作
*/
public void setOnDateTimeChangedListener(OnDateTimeChangedListener callback) {
// 设置日期时间改变的回调函数
mOnDateTimeChangedListener = callback;
}
// 触发日期时间改变的回调
private void onDateTimeChanged() {
if (mOnDateTimeChangedListener != null) {
// 调用回调函数,传递当前的年、月、日、小时和分钟
mOnDateTimeChangedListener.onDateTimeChanged(this, getCurrentYear(),
getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute());
}
}
}