zuizhongjieguo

pull/2/head
lyl 19 hours ago
parent e88b3cb3c4
commit 52f3eb0b9c

@ -0,0 +1 @@
Subproject commit 85ad4e7b6c62b539ad3bffcdf964e05becfa0bba

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

@ -28,37 +28,52 @@ import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
// 定义一个名为AlarmInitReceiver的类继承自BroadcastReceiver
public class AlarmInitReceiver extends BroadcastReceiver {
// 定义一个字符串数组包含NoteColumns中的ID和ALERTED_DATE
private static final String [] PROJECTION = new String [] {
NoteColumns.ID,
NoteColumns.ALERTED_DATE
};
// 定义两个常量分别表示ID和ALERTED_DATE的列索引
private static final int COLUMN_ID = 0;
private static final int COLUMN_ALERTED_DATE = 1;
@Override
public void onReceive(Context context, Intent intent) {
// 获取当前时间
long currentDate = System.currentTimeMillis();
// 查询数据库,获取所有未提醒的笔记
Cursor c = context.getContentResolver().query(Notes.CONTENT_NOTE_URI,
PROJECTION,
NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE,
new String[] { String.valueOf(currentDate) },
null);
// 如果c不为空
if (c != null) {
// 如果c可以移动到第一行
if (c.moveToFirst()) {
// 循环遍历c
do {
// 获取提醒日期
long alertDate = c.getLong(COLUMN_ALERTED_DATE);
// 创建一个Intent指向AlarmReceiver类
Intent sender = new Intent(context, AlarmReceiver.class);
// 设置Intent的数据指向Notes.CONTENT_NOTE_URI并添加c.getLong(COLUMN_ID)作为参数
sender.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(COLUMN_ID)));
// 创建一个PendingIntent用于发送广播
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, sender, 0);
// 获取AlarmManager服务
AlarmManager alermManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
// 设置闹钟在alertDate时间点唤醒设备并发送广播
alermManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent);
} while (c.moveToNext());
}
// 关闭c
c.close();
}
}

@ -67,8 +67,11 @@ public class DateTimePicker extends FrameLayout {
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();
}
};
@ -76,37 +79,52 @@ public class DateTimePicker extends FrameLayout {
private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
// 判断是否日期改变
boolean isDateChanged = false;
// 获取当前时间
Calendar cal = Calendar.getInstance();
// 判断是否为24小时制
if (!mIs24HourView) {
// 判断是否为上午
if (!mIsAm && oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) {
// 如果当前时间是上午11点并且选择的时间是下午12点则日期加1天
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) {
// 如果当前时间是下午12点并且选择的时间是上午11点则日期减1天
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, -1);
isDateChanged = true;
}
// 判断是否跨过12点
if (oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY ||
oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) {
// 跨过12点则上午和下午互换
mIsAm = !mIsAm;
updateAmPmControl();
}
} else {
// 判断是否跨过24点
if (oldVal == HOURS_IN_ALL_DAY - 1 && newVal == 0) {
// 如果当前时间是23点并且选择的时间是0点则日期加1天
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, 1);
isDateChanged = true;
} else if (oldVal == 0 && newVal == HOURS_IN_ALL_DAY - 1) {
// 如果当前时间是0点并且选择的时间是23点则日期减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));
@ -118,84 +136,120 @@ public class DateTimePicker extends FrameLayout {
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;
// 如果旧值等于最大值且新值等于最小值则偏移量为1
if (oldVal == maxValue && newVal == minValue) {
offset += 1;
// 如果旧值等于最小值且新值等于最大值,则偏移量为-1
} else if (oldVal == minValue && newVal == maxValue) {
offset -= 1;
}
// 如果偏移量不为0则更新日期和时间
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();
}
};
// 定义一个NumberPicker的值改变监听器
private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
// 切换AM/PM
mIsAm = !mIsAm;
// 如果是AM则将时间减去12小时
if (mIsAm) {
mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY);
// 如果是PM则将时间加上12小时
} else {
mDate.add(Calendar.HOUR_OF_DAY, HOURS_IN_HALF_DAY);
}
// 更新AM/PM控制
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;
// 判断当前小时是否大于等于12
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);
// update controls to initial state
@ -215,20 +269,29 @@ public class DateTimePicker extends FrameLayout {
}
@Override
// 重写setEnabled方法
public void setEnabled(boolean enabled) {
// 如果当前状态和传入的状态相同,则直接返回
if (mIsEnabled == enabled) {
return;
}
// 调用父类的setEnabled方法
super.setEnabled(enabled);
// 设置日期选择器是否可用
mDateSpinner.setEnabled(enabled);
// 设置分钟选择器是否可用
mMinuteSpinner.setEnabled(enabled);
// 设置小时选择器是否可用
mHourSpinner.setEnabled(enabled);
// 设置上午/下午选择器是否可用
mAmPmSpinner.setEnabled(enabled);
// 更新当前状态
mIsEnabled = enabled;
}
@Override
public boolean isEnabled() {
// 返回mIsEnabled的值
return mIsEnabled;
}
@ -247,8 +310,11 @@ public class DateTimePicker extends FrameLayout {
* @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));
}
@ -264,10 +330,15 @@ public class DateTimePicker extends FrameLayout {
*/
public void setCurrentDate(int year, int month,
int dayOfMonth, int hourOfDay, int minute) {
// 设置当前年份
setCurrentYear(year);
// 设置当前月份
setCurrentMonth(month);
// 设置当前日期
setCurrentDay(dayOfMonth);
// 设置当前小时
setCurrentHour(hourOfDay);
// 设置当前分钟
setCurrentMinute(minute);
}
@ -277,6 +348,7 @@ public class DateTimePicker extends FrameLayout {
* @return The current year
*/
public int getCurrentYear() {
// 获取当前年份
return mDate.get(Calendar.YEAR);
}
@ -286,11 +358,15 @@ public class DateTimePicker extends FrameLayout {
* @param year The current year
*/
public void setCurrentYear(int year) {
// 如果当前年份与传入的年份相同,则不进行任何操作
if (!mInitialising && year == getCurrentYear()) {
return;
}
// 设置当前年份
mDate.set(Calendar.YEAR, year);
// 更新日期控件
updateDateControl();
// 日期时间改变
onDateTimeChanged();
}
@ -300,6 +376,7 @@ public class DateTimePicker extends FrameLayout {
* @return The current month in the year
*/
public int getCurrentMonth() {
// 获取当前月份
return mDate.get(Calendar.MONTH);
}
@ -309,11 +386,15 @@ public class DateTimePicker extends FrameLayout {
* @param month The month in the year
*/
public void setCurrentMonth(int month) {
// 如果当前月份和要设置的月份相同,则不进行设置
if (!mInitialising && month == getCurrentMonth()) {
return;
}
// 设置当前月份
mDate.set(Calendar.MONTH, month);
// 更新日期控件
updateDateControl();
// 日期改变回调
onDateTimeChanged();
}
@ -322,7 +403,9 @@ public class DateTimePicker extends FrameLayout {
*
* @return The day of the month
*/
// 获取当前日期
public int getCurrentDay() {
// 获取当前日期的日
return mDate.get(Calendar.DAY_OF_MONTH);
}
@ -332,11 +415,15 @@ public class DateTimePicker extends FrameLayout {
* @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();
}
@ -344,18 +431,26 @@ public class DateTimePicker extends FrameLayout {
* 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() {
// 如果是24小时制
if (mIs24HourView){
// 获取当前小时
return getCurrentHourOfDay();
} else {
// 获取当前小时
int hour = getCurrentHourOfDay();
// 如果当前小时大于12
if (hour > HOURS_IN_HALF_DAY) {
// 返回当前小时减去12
return hour - HOURS_IN_HALF_DAY;
} else {
// 如果当前小时等于0返回12
return hour == 0 ? HOURS_IN_HALF_DAY : hour;
}
}
@ -366,26 +461,40 @@ public class DateTimePicker extends FrameLayout {
*
* @param hourOfDay
*/
// 设置当前小时
public void setCurrentHour(int hourOfDay) {
// 如果当前正在初始化,或者当前小时和要设置的小时相同,则直接返回
if (!mInitialising && hourOfDay == getCurrentHourOfDay()) {
return;
}
// 设置当前小时
mDate.set(Calendar.HOUR_OF_DAY, hourOfDay);
// 如果不是24小时制
if (!mIs24HourView) {
// 如果当前小时大于等于12
if (hourOfDay >= HOURS_IN_HALF_DAY) {
// 设置为下午
mIsAm = false;
// 如果当前小时大于12
if (hourOfDay > HOURS_IN_HALF_DAY) {
// 当前小时减去12
hourOfDay -= HOURS_IN_HALF_DAY;
}
} else {
// 设置为上午
mIsAm = true;
// 如果当前小时为0
if (hourOfDay == 0) {
// 当前小时设置为12
hourOfDay = HOURS_IN_HALF_DAY;
}
}
// 更新上午/下午控制
updateAmPmControl();
}
// 设置小时选择器的值
mHourSpinner.setValue(hourOfDay);
// 日期时间改变
onDateTimeChanged();
}
@ -394,6 +503,7 @@ public class DateTimePicker extends FrameLayout {
*
* @return The Current Minute
*/
// 获取当前分钟
public int getCurrentMinute() {
return mDate.get(Calendar.MINUTE);
}
@ -402,17 +512,22 @@ public class DateTimePicker extends FrameLayout {
* Set current minute
*/
public void setCurrentMinute(int minute) {
// 如果mInitialising为false且minute等于getCurrentMinute(),则直接返回
if (!mInitialising && minute == getCurrentMinute()) {
return;
}
// 设置mMinuteSpinner的值为minute
mMinuteSpinner.setValue(minute);
// 设置mDate的分钟为minute
mDate.set(Calendar.MINUTE, minute);
// 调用onDateTimeChanged()方法
onDateTimeChanged();
}
/**
* @return true if this is in 24 hour view else false.
*/
// 判断是否为24小时制
public boolean is24HourView () {
return mIs24HourView;
}
@ -423,47 +538,73 @@ public class DateTimePicker extends FrameLayout {
* @param is24HourView True for 24 hour mode. False for AM/PM mode.
*/
public void set24HourView(boolean is24HourView) {
// 如果当前时间格式和传入的时间格式相同,则直接返回
if (mIs24HourView == is24HourView) {
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();
// 将当前日期设置为mDate的时间
cal.setTimeInMillis(mDate.getTimeInMillis());
// 将当前日期向前推DAYS_IN_ALL_WEEK / 2 - 1天
cal.add(Calendar.DAY_OF_YEAR, -DAYS_IN_ALL_WEEK / 2 - 1);
// 清空mDateSpinner的显示值
mDateSpinner.setDisplayedValues(null);
// 循环DAYS_IN_ALL_WEEK次
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的显示值设置为mDateDisplayValues
mDateSpinner.setDisplayedValues(mDateDisplayValues);
// 将mDateSpinner的值设置为DAYS_IN_ALL_WEEK / 2
mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2);
// 使mDateSpinner无效
mDateSpinner.invalidate();
}
private void updateAmPmControl() {
// 如果是24小时制则隐藏上午/下午选择器
if (mIs24HourView) {
mAmPmSpinner.setVisibility(View.GONE);
} else {
// 如果是上午,则选择上午,否则选择下午
int index = mIsAm ? Calendar.AM : Calendar.PM;
mAmPmSpinner.setValue(index);
// 显示上午/下午选择器
mAmPmSpinner.setVisibility(View.VISIBLE);
}
}
// 更新小时控件
private void updateHourControl() {
// 如果是24小时制
if (mIs24HourView) {
// 设置小时选择器的最小值为24小时制最小值
mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW);
// 设置小时选择器的最大值为24小时制最大值
mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW);
} else {
// 设置小时选择器的最小值为12小时制最小值
mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW);
// 设置小时选择器的最大值为12小时制最大值
mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW);
}
}
@ -472,12 +613,16 @@ public class DateTimePicker extends FrameLayout {
* 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) {
// 调用日期时间改变监听器的onDateTimeChanged方法并传入当前日期时间
mOnDateTimeChangedListener.onDateTimeChanged(this, getCurrentYear(),
getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute());
}

@ -31,57 +31,83 @@ import android.text.format.DateUtils;
public class DateTimePickerDialog extends AlertDialog implements OnClickListener {
// 定义一个Calendar对象用于存储日期和时间
private Calendar mDate = Calendar.getInstance();
// 定义一个布尔变量用于判断是否为24小时制
private boolean mIs24HourView;
// 定义一个OnDateTimeSetListener对象用于监听日期时间的设置
private OnDateTimeSetListener mOnDateTimeSetListener;
// 定义一个DateTimePicker对象用于显示日期时间选择器
private DateTimePicker mDateTimePicker;
// 定义一个接口,用于监听日期时间设置
public interface OnDateTimeSetListener {
// 当日期时间设置时,调用此方法
void OnDateTimeSet(AlertDialog dialog, long date);
}
// 定义一个DateTimePickerDialog类传入Context和long类型的date参数
public DateTimePickerDialog(Context context, long date) {
// 调用父类的构造方法
super(context);
// 创建一个DateTimePicker对象
mDateTimePicker = new DateTimePicker(context);
// 设置视图
setView(mDateTimePicker);
// 设置DateTimePicker的监听器
mDateTimePicker.setOnDateTimeChangedListener(new OnDateTimeChangedListener() {
public void onDateTimeChanged(DateTimePicker view, int year, int month,
int dayOfMonth, int hourOfDay, int minute) {
// 设置日期
mDate.set(Calendar.YEAR, year);
mDate.set(Calendar.MONTH, month);
mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
mDate.set(Calendar.HOUR_OF_DAY, hourOfDay);
mDate.set(Calendar.MINUTE, minute);
// 更新标题
updateTitle(mDate.getTimeInMillis());
}
});
// 设置日期
mDate.setTimeInMillis(date);
mDate.set(Calendar.SECOND, 0);
// 设置当前日期
mDateTimePicker.setCurrentDate(mDate.getTimeInMillis());
// 设置按钮
setButton(context.getString(R.string.datetime_dialog_ok), this);
setButton2(context.getString(R.string.datetime_dialog_cancel), (OnClickListener)null);
// 设置24小时制
set24HourView(DateFormat.is24HourFormat(this.getContext()));
// 更新标题
updateTitle(mDate.getTimeInMillis());
}
// 设置是否为24小时制
public void set24HourView(boolean is24HourView) {
mIs24HourView = is24HourView;
}
// 设置日期时间设置监听器
public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) {
// 将传入的监听器赋值给成员变量
mOnDateTimeSetListener = callBack;
}
// 更新标题
private void updateTitle(long date) {
// 设置日期格式
int flag =
DateUtils.FORMAT_SHOW_YEAR |
DateUtils.FORMAT_SHOW_DATE |
DateUtils.FORMAT_SHOW_TIME;
// 如果是24小时制则设置格式为24小时制
flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR;
// 格式化日期并设置标题
setTitle(DateUtils.formatDateTime(this.getContext(), date, flag));
}
public void onClick(DialogInterface arg0, int arg1) {
// 如果mOnDateTimeSetListener不为空则调用其OnDateTimeSet方法传入当前对象和mDate的时间戳
if (mOnDateTimeSetListener != null) {
mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis());
}

@ -30,49 +30,68 @@ import net.micode.notes.data.Notes.NoteColumns;
public class FoldersListAdapter extends CursorAdapter {
// 定义一个静态常量,用于存储查询结果的列名
public static final String [] PROJECTION = {
NoteColumns.ID,
NoteColumns.SNIPPET
NoteColumns.ID, // 存储笔记的ID
NoteColumns.SNIPPET // 存储笔记的摘要
};
// 定义ID列的常量
public static final int ID_COLUMN = 0;
// 定义名称列的常量
public static final int NAME_COLUMN = 1;
// 构造函数用于初始化FoldersListAdapter对象
public FoldersListAdapter(Context context, Cursor c) {
super(context, c);
// TODO Auto-generated constructor stub
}
@Override
// 重写newView方法用于创建新的视图
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// 创建一个新的FolderListItem视图
return new FolderListItem(context);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
// 判断view是否为FolderListItem类型
if (view instanceof FolderListItem) {
// 获取文件夹名称
String folderName = (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
// 绑定文件夹名称
((FolderListItem) view).bind(folderName);
}
}
// 根据位置获取文件夹名称
public String getFolderName(Context context, int position) {
// 获取指定位置的Cursor对象
Cursor cursor = (Cursor) getItem(position);
// 如果Cursor对象的ID列的值为Notes.ID_ROOT_FOLDER则返回菜单移动到父文件夹的字符串否则返回Cursor对象的NAME列的值
return (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
}
// 定义一个内部类FolderListItem继承自LinearLayout
private class FolderListItem extends LinearLayout {
// 定义一个TextView变量mName
private TextView mName;
// 构造方法传入Context参数
public FolderListItem(Context context) {
super(context);
// 使用inflate方法加载布局文件R.layout.folder_list_item并将布局文件添加到当前LinearLayout中
inflate(context, R.layout.folder_list_item, this);
// 通过findViewById方法获取布局文件中的TextView控件并赋值给mName变量
mName = (TextView) findViewById(R.id.tv_folder_name);
}
// 绑定方法传入一个String参数name
public void bind(String name) {
// 将传入的name参数设置给mName控件的文本
mName.setText(name);
}
}

@ -74,18 +74,26 @@ import java.util.regex.Pattern;
public class NoteEditActivity extends Activity implements OnClickListener,
NoteSettingChangedListener, OnTextViewChangeListener {
// 定义一个内部类HeadViewHolder用于保存头部视图的控件
private class HeadViewHolder {
// 保存修改日期的TextView
public TextView tvModified;
// 保存提醒图标的ImageView
public ImageView ivAlertIcon;
// 保存提醒日期的TextView
public TextView tvAlertDate;
// 保存设置背景颜色的ImageView
public ImageView ibSetBgColor;
}
// 定义一个静态的Map用于存储背景选择按钮的ID和对应的颜色值
private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>();
// 静态代码块用于初始化Map
static {
// 将背景选择按钮的ID和对应的颜色值放入Map中
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
sBgSelectorBtnsMap.put(R.id.iv_bg_red, ResourceParser.RED);
sBgSelectorBtnsMap.put(R.id.iv_bg_blue, ResourceParser.BLUE);
@ -94,16 +102,24 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private static final Map<Integer, Integer> sBgSelectorSelectionMap = new HashMap<Integer, Integer>();
// 初始化静态变量sBgSelectorSelectionMap用于存储背景选择器的资源ID
static {
// 将ResourceParser.YELLOW对应的资源ID存入sBgSelectorSelectionMap
sBgSelectorSelectionMap.put(ResourceParser.YELLOW, R.id.iv_bg_yellow_select);
// 将ResourceParser.RED对应的资源ID存入sBgSelectorSelectionMap
sBgSelectorSelectionMap.put(ResourceParser.RED, R.id.iv_bg_red_select);
// 将ResourceParser.BLUE对应的资源ID存入sBgSelectorSelectionMap
sBgSelectorSelectionMap.put(ResourceParser.BLUE, R.id.iv_bg_blue_select);
// 将ResourceParser.GREEN对应的资源ID存入sBgSelectorSelectionMap
sBgSelectorSelectionMap.put(ResourceParser.GREEN, R.id.iv_bg_green_select);
// 将ResourceParser.WHITE对应的资源ID存入sBgSelectorSelectionMap
sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select);
}
// 定义一个静态常量用于存储字体大小按钮的ID和对应的字体大小
private static final Map<Integer, Integer> sFontSizeBtnsMap = new HashMap<Integer, Integer>();
static {
// 将字体大小按钮的ID和对应的字体大小放入Map中
sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE);
sFontSizeBtnsMap.put(R.id.ll_font_small, ResourceParser.TEXT_SMALL);
sFontSizeBtnsMap.put(R.id.ll_font_normal, ResourceParser.TEXT_MEDIUM);
@ -111,6 +127,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private static final Map<Integer, Integer> sFontSelectorSelectionMap = new HashMap<Integer, Integer>();
// 初始化字体选择器选择映射
static {
sFontSelectorSelectionMap.put(ResourceParser.TEXT_LARGE, R.id.iv_large_select);
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SMALL, R.id.iv_small_select);
@ -120,45 +137,67 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private static final String TAG = "NoteEditActivity";
// 头部视图持有者
private HeadViewHolder mNoteHeaderHolder;
// 头部视图面板
private View mHeadViewPanel;
// 笔记背景颜色选择器
private View mNoteBgColorSelector;
// 字体大小选择器
private View mFontSizeSelector;
// 笔记编辑器
private EditText mNoteEditor;
// 笔记编辑器面板
private View mNoteEditorPanel;
// 工作中的笔记
private WorkingNote mWorkingNote;
// 共享偏好设置
private SharedPreferences mSharedPrefs;
// 字体大小ID
private int mFontSizeId;
// 字体大小偏好设置键
private static final String PREFERENCE_FONT_SIZE = "pref_font_size";
// 快捷图标标题最大长度
private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10;
// 已选中的标签
public static final String TAG_CHECKED = String.valueOf('\u221A');
// 未选中的标签
public static final String TAG_UNCHECKED = String.valueOf('\u25A1');
// 编辑文本列表
private LinearLayout mEditTextList;
// 用户查询
private String mUserQuery;
// 正则表达式
private Pattern mPattern;
@Override
// 重写onCreate方法
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 调用父类的onCreate方法
this.setContentView(R.layout.note_edit);
// 设置当前Activity的布局文件为note_edit.xml
if (savedInstanceState == null && !initActivityState(getIntent())) {
// 如果savedInstanceState为空且initActivityState方法返回false
finish();
// 结束当前Activity
return;
}
initResources();
// 初始化资源
}
/**
@ -166,16 +205,25 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* user load this activity, we should restore the former state
*/
@Override
// 重写onRestoreInstanceState方法
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// 调用父类的onRestoreInstanceState方法
if (savedInstanceState != null && savedInstanceState.containsKey(Intent.EXTRA_UID)) {
// 如果savedInstanceState不为空且包含Intent.EXTRA_UID键
Intent intent = new Intent(Intent.ACTION_VIEW);
// 创建一个Intent对象并设置Action为Intent.ACTION_VIEW
intent.putExtra(Intent.EXTRA_UID, savedInstanceState.getLong(Intent.EXTRA_UID));
// 将savedInstanceState中的Intent.EXTRA_UID键对应的值添加到Intent对象中
if (!initActivityState(intent)) {
// 如果initActivityState方法返回false
finish();
// 结束当前Activity
return;
}
// 如果initActivityState方法返回true
Log.d(TAG, "Restoring from killed activity");
// 打印日志表示从被杀掉的Activity中恢复
}
}
@ -197,6 +245,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY);
}
// Check if the note exists
if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) {
Intent jump = new Intent(this, NotesListActivity.class);
startActivity(jump);
@ -204,6 +253,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
finish();
return false;
} else {
// Load the note
mWorkingNote = WorkingNote.load(this, noteId);
if (mWorkingNote == null) {
Log.e(TAG, "load note failed with note id" + noteId);
@ -211,6 +261,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return false;
}
}
// Set the soft input mode
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
@ -250,6 +301,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
bgResId);
}
// Set the soft input mode
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
@ -258,6 +310,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
finish();
return false;
}
// Set the listener for the note
mWorkingNote.setOnSettingStatusChangedListener(this);
return true;
}
@ -265,24 +318,33 @@ public class NoteEditActivity extends Activity implements OnClickListener,
@Override
protected void onResume() {
super.onResume();
// Initialize the note screen
initNoteScreen();
}
private void initNoteScreen() {
// Set the text appearance of the note editor
mNoteEditor.setTextAppearance(this, TextAppearanceResources
.getTexAppearanceResource(mFontSizeId));
// Check if the note is in check list mode
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
// Switch to list mode
switchToListMode(mWorkingNote.getContent());
} else {
// Set the text of the note editor
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
// Set the selection of the note editor
mNoteEditor.setSelection(mNoteEditor.getText().length());
}
// Set the visibility of the background selector
for (Integer id : sBgSelectorSelectionMap.keySet()) {
findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE);
}
// Set the background of the header and note editor panel
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
// Set the modified date of the note
mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(this,
mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
| DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
@ -292,29 +354,42 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* TODO: Add the menu for setting alert. Currently disable it because the DateTimePicker
* is not ready
*/
// Show the alert header
showAlertHeader();
}
private void showAlertHeader() {
// 如果当前笔记设置了提醒
if (mWorkingNote.hasClockAlert()) {
// 获取当前时间
long time = System.currentTimeMillis();
// 如果当前时间大于提醒时间
if (time > mWorkingNote.getAlertDate()) {
// 设置提醒日期为已过期
mNoteHeaderHolder.tvAlertDate.setText(R.string.note_alert_expired);
} else {
// 设置提醒日期为相对时间
mNoteHeaderHolder.tvAlertDate.setText(DateUtils.getRelativeTimeSpanString(
mWorkingNote.getAlertDate(), time, DateUtils.MINUTE_IN_MILLIS));
}
// 显示提醒日期
mNoteHeaderHolder.tvAlertDate.setVisibility(View.VISIBLE);
// 显示提醒图标
mNoteHeaderHolder.ivAlertIcon.setVisibility(View.VISIBLE);
} else {
// 隐藏提醒日期
mNoteHeaderHolder.tvAlertDate.setVisibility(View.GONE);
// 隐藏提醒图标
mNoteHeaderHolder.ivAlertIcon.setVisibility(View.GONE);
};
}
// 重写onNewIntent方法
@Override
protected void onNewIntent(Intent intent) {
// 调用父类的onNewIntent方法
super.onNewIntent(intent);
// 初始化活动状态
initActivityState(intent);
}
@ -326,64 +401,93 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* generate a id. If the editing note is not worth saving, there
* is no id which is equivalent to create new note
*/
// 如果当前编辑的笔记没有note id我们首先应该保存它以生成一个id。如果编辑的笔记不值得保存那么没有id相当于创建新笔记
if (!mWorkingNote.existInDatabase()) {
saveNote();
}
// 将当前编辑的笔记的id保存到Bundle中
outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId());
// 打印日志记录当前编辑的笔记的id
Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState");
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// 如果mNoteBgColorSelector可见且不在mNoteBgColorSelector范围内则隐藏mNoteBgColorSelector
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE
&& !inRangeOfView(mNoteBgColorSelector, ev)) {
mNoteBgColorSelector.setVisibility(View.GONE);
return true;
}
// 如果mFontSizeSelector可见且不在mFontSizeSelector范围内则隐藏mFontSizeSelector
if (mFontSizeSelector.getVisibility() == View.VISIBLE
&& !inRangeOfView(mFontSizeSelector, ev)) {
mFontSizeSelector.setVisibility(View.GONE);
return true;
}
// 否则调用父类的dispatchTouchEvent方法
return super.dispatchTouchEvent(ev);
}
private boolean inRangeOfView(View view, MotionEvent ev) {
// 获取view在屏幕上的位置
int []location = new int[2];
view.getLocationOnScreen(location);
// 获取view的x坐标
int x = location[0];
// 获取view的y坐标
int y = location[1];
// 判断ev的x坐标是否在view的范围内
if (ev.getX() < x
// 判断ev的x坐标是否在view的范围内
|| ev.getX() > (x + view.getWidth())
// 判断ev的y坐标是否在view的范围内
|| ev.getY() < y
// 判断ev的y坐标是否在view的范围内
|| ev.getY() > (y + view.getHeight())) {
// 如果不在范围内返回false
return false;
}
// 如果在范围内返回true
return true;
}
private void initResources() {
// 初始化标题栏
mHeadViewPanel = findViewById(R.id.note_title);
// 初始化标题栏的ViewHolder
mNoteHeaderHolder = new HeadViewHolder();
// 初始化标题栏中的修改日期TextView
mNoteHeaderHolder.tvModified = (TextView) findViewById(R.id.tv_modified_date);
// 初始化标题栏中的提醒图标ImageView
mNoteHeaderHolder.ivAlertIcon = (ImageView) findViewById(R.id.iv_alert_icon);
// 初始化标题栏中的提醒日期TextView
mNoteHeaderHolder.tvAlertDate = (TextView) findViewById(R.id.tv_alert_date);
// 初始化标题栏中的设置背景颜色按钮ImageView
mNoteHeaderHolder.ibSetBgColor = (ImageView) findViewById(R.id.btn_set_bg_color);
// 设置设置背景颜色按钮的点击事件
mNoteHeaderHolder.ibSetBgColor.setOnClickListener(this);
// 初始化笔记编辑框
mNoteEditor = (EditText) findViewById(R.id.note_edit_view);
// 初始化笔记编辑框的面板
mNoteEditorPanel = findViewById(R.id.sv_note_edit);
// 初始化笔记背景颜色选择器
mNoteBgColorSelector = findViewById(R.id.note_bg_color_selector);
// 遍历背景颜色选择器中的按钮,并设置点击事件
for (int id : sBgSelectorBtnsMap.keySet()) {
ImageView iv = (ImageView) findViewById(id);
iv.setOnClickListener(this);
}
// 初始化字体大小选择器
mFontSizeSelector = findViewById(R.id.font_size_selector);
// 遍历字体大小选择器中的按钮,并设置点击事件
for (int id : sFontSizeBtnsMap.keySet()) {
View view = findViewById(id);
view.setOnClickListener(this);
};
// 获取默认的SharedPreferences
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
mFontSizeId = mSharedPrefs.getInt(PREFERENCE_FONT_SIZE, ResourceParser.BG_DEFAULT_FONT_SIZE);
/**
@ -397,121 +501,176 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
}
// 重写onPause方法
@Override
protected void onPause() {
// 调用父类的onPause方法
super.onPause();
// 如果保存笔记数据成功
if(saveNote()) {
// 打印日志,显示笔记数据的长度
Log.d(TAG, "Note data was saved with length:" + mWorkingNote.getContent().length());
}
// 清除设置状态
clearSettingState();
}
private void updateWidget() {
// 创建一个Intent用于更新AppWidget
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
// 判断当前笔记的Widget类型
if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) {
// 如果是2x类型的Widget设置Intent的Class为NoteWidgetProvider_2x
intent.setClass(this, NoteWidgetProvider_2x.class);
} else if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_4X) {
// 如果是4x类型的Widget设置Intent的Class为NoteWidgetProvider_4x
intent.setClass(this, NoteWidgetProvider_4x.class);
} else {
// 如果是其他类型的Widget输出错误日志并返回
Log.e(TAG, "Unspported widget type");
return;
}
// 将当前笔记的WidgetId添加到Intent中
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
mWorkingNote.getWidgetId()
});
// 发送广播更新AppWidget
sendBroadcast(intent);
// 设置结果为RESULT_OK
setResult(RESULT_OK, intent);
}
public void onClick(View v) {
// 获取点击的View的id
int id = v.getId();
// 如果点击的是设置背景颜色的按钮
if (id == R.id.btn_set_bg_color) {
// 显示背景颜色选择器
mNoteBgColorSelector.setVisibility(View.VISIBLE);
// 显示当前背景颜色选择器
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
- View.VISIBLE);
// 如果点击的是背景颜色选择器中的按钮
} else if (sBgSelectorBtnsMap.containsKey(id)) {
// 隐藏当前背景颜色选择器
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.GONE);
// 设置当前背景颜色
mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));
// 隐藏背景颜色选择器
mNoteBgColorSelector.setVisibility(View.GONE);
// 如果点击的是字体大小选择器中的按钮
} else if (sFontSizeBtnsMap.containsKey(id)) {
// 隐藏当前字体大小选择器
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.GONE);
// 设置当前字体大小
mFontSizeId = sFontSizeBtnsMap.get(id);
// 保存当前字体大小到SharedPreferences
mSharedPrefs.edit().putInt(PREFERENCE_FONT_SIZE, mFontSizeId).commit();
// 显示当前字体大小选择器
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);
// 如果当前笔记处于清单模式
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
// 获取当前笔记内容
getWorkingText();
// 切换到清单模式
switchToListMode(mWorkingNote.getContent());
// 如果当前笔记不处于清单模式
} else {
// 设置当前笔记的字体大小
mNoteEditor.setTextAppearance(this,
TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
}
// 隐藏字体大小选择器
mFontSizeSelector.setVisibility(View.GONE);
}
}
@Override
public void onBackPressed() {
// 如果清除设置状态成功,则直接返回
if(clearSettingState()) {
return;
}
// 保存笔记
saveNote();
// 调用父类的方法
super.onBackPressed();
}
private boolean clearSettingState() {
// 如果mNoteBgColorSelector可见则将其设置为不可见并返回true
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE) {
mNoteBgColorSelector.setVisibility(View.GONE);
return true;
// 如果mFontSizeSelector可见则将其设置为不可见并返回true
} else if (mFontSizeSelector.getVisibility() == View.VISIBLE) {
mFontSizeSelector.setVisibility(View.GONE);
return true;
}
// 如果以上两种情况都不满足则返回false
return false;
}
// 当背景颜色改变时调用
public void onBackgroundColorChanged() {
// 根据当前笔记的背景颜色ID找到对应的背景颜色选择器并将其可见性设置为可见
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.VISIBLE);
// 设置笔记编辑面板的背景颜色为当前笔记的背景颜色资源ID
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
// 设置标题面板的背景颜色为当前笔记的标题背景颜色资源ID
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// 如果Activity正在结束则返回true
if (isFinishing()) {
return true;
}
// 清除设置状态
clearSettingState();
// 清空菜单
menu.clear();
// 如果当前笔记是通话记录,则加载通话记录编辑菜单
if (mWorkingNote.getFolderId() == Notes.ID_CALL_RECORD_FOLDER) {
getMenuInflater().inflate(R.menu.call_note_edit, menu);
// 否则加载普通编辑菜单
} else {
getMenuInflater().inflate(R.menu.note_edit, menu);
}
// 如果当前笔记是清单模式,则将菜单项的标题设置为普通模式
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
menu.findItem(R.id.menu_list_mode).setTitle(R.string.menu_normal_mode);
// 否则将菜单项的标题设置为清单模式
} else {
menu.findItem(R.id.menu_list_mode).setTitle(R.string.menu_list_mode);
}
// 如果当前笔记有闹钟提醒,则隐藏提醒菜单项
if (mWorkingNote.hasClockAlert()) {
menu.findItem(R.id.menu_alert).setVisible(false);
// 否则隐藏删除提醒菜单项
} else {
menu.findItem(R.id.menu_delete_remind).setVisible(false);
}
// 返回true
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// 根据菜单项的id执行相应的操作
switch (item.getItemId()) {
case R.id.menu_new_note:
// 创建新笔记
createNewNote();
break;
case R.id.menu_delete:
// 弹出删除确认对话框
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.alert_title_delete));
builder.setIcon(android.R.drawable.ic_dialog_alert);
@ -519,6 +678,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 删除当前笔记并关闭活动
deleteCurrentNote();
finish();
}
@ -527,24 +687,30 @@ public class NoteEditActivity extends Activity implements OnClickListener,
builder.show();
break;
case R.id.menu_font_size:
// 显示字体大小选择器
mFontSizeSelector.setVisibility(View.VISIBLE);
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);
break;
case R.id.menu_list_mode:
// 切换列表模式
mWorkingNote.setCheckListMode(mWorkingNote.getCheckListMode() == 0 ?
TextNote.MODE_CHECK_LIST : 0);
break;
case R.id.menu_share:
// 获取当前笔记内容并分享
getWorkingText();
sendTo(this, mWorkingNote.getContent());
break;
case R.id.menu_send_to_desktop:
// 发送到桌面
sendToDesktop();
break;
case R.id.menu_alert:
// 设置提醒
setReminder();
break;
case R.id.menu_delete_remind:
// 删除提醒
mWorkingNote.setAlertDate(0, false);
break;
default:
@ -554,12 +720,17 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private void setReminder() {
// 创建一个DateTimePickerDialog对象参数为当前上下文和当前时间
DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis());
// 设置DateTimePickerDialog的监听器
d.setOnDateTimeSetListener(new OnDateTimeSetListener() {
// 当日期时间被设置时,调用此方法
public void OnDateTimeSet(AlertDialog dialog, long date) {
// 设置工作笔记的提醒日期
mWorkingNote.setAlertDate(date , true);
}
});
// 显示DateTimePickerDialog
d.show();
}
@ -567,10 +738,15 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* Share note to apps that support {@link Intent#ACTION_SEND} action
* and {@text/plain} type
*/
// 向指定上下文发送信息
private void sendTo(Context context, String info) {
// 创建一个发送意图
Intent intent = new Intent(Intent.ACTION_SEND);
// 将信息添加到意图中
intent.putExtra(Intent.EXTRA_TEXT, info);
// 设置意图的类型为文本
intent.setType("text/plain");
// 启动意图
context.startActivity(intent);
}
@ -586,29 +762,44 @@ public class NoteEditActivity extends Activity implements OnClickListener,
startActivity(intent);
}
// 删除当前笔记
private void deleteCurrentNote() {
// 如果当前笔记存在于数据库中
if (mWorkingNote.existInDatabase()) {
// 创建一个HashSet来存储要删除的笔记的id
HashSet<Long> ids = new HashSet<Long>();
// 获取当前笔记的id
long id = mWorkingNote.getNoteId();
// 如果当前笔记的id不是根文件夹的id
if (id != Notes.ID_ROOT_FOLDER) {
// 将当前笔记的id添加到HashSet中
ids.add(id);
} else {
// 如果当前笔记的id是根文件夹的id则打印错误日志
Log.d(TAG, "Wrong note id, should not happen");
}
// 如果当前不是同步模式
if (!isSyncMode()) {
// 批量删除笔记
if (!DataUtils.batchDeleteNotes(getContentResolver(), ids)) {
// 如果删除失败,则打印错误日志
Log.e(TAG, "Delete Note error");
}
} else {
// 如果是同步模式
if (!DataUtils.batchMoveToFolder(getContentResolver(), ids, Notes.ID_TRASH_FOLER)) {
// 如果移动到垃圾桶文件夹失败,则打印错误日志
Log.e(TAG, "Move notes to trash folder error, should not happens");
}
}
}
// 标记当前笔记为已删除
mWorkingNote.markDeleted(true);
}
// 判断是否为同步模式
private boolean isSyncMode() {
// 获取同步账户名称
return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
}
@ -642,22 +833,29 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
}
// 当小部件发生变化时调用
public void onWidgetChanged() {
// 更新小部件
updateWidget();
}
public void onEditTextDelete(int index, String text) {
// 获取EditTextList的子视图数量
int childCount = mEditTextList.getChildCount();
// 如果子视图数量为1则直接返回
if (childCount == 1) {
return;
}
// 从被删除的EditText的下一个开始依次将每个EditText的索引减1
for (int i = index + 1; i < childCount; i++) {
((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text))
.setIndex(i - 1);
}
// 从EditTextList中移除被删除的EditText
mEditTextList.removeViewAt(index);
// 获取被删除的EditText的前一个EditText
NoteEditText edit = null;
if(index == 0) {
edit = (NoteEditText) mEditTextList.getChildAt(0).findViewById(
@ -666,9 +864,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
edit = (NoteEditText) mEditTextList.getChildAt(index - 1).findViewById(
R.id.et_edit_text);
}
// 获取被删除的EditText的长度
int length = edit.length();
// 将被删除的EditText的内容追加到前一个EditText中
edit.append(text);
// 将焦点设置到前一个EditText中
edit.requestFocus();
// 将光标设置到前一个EditText的末尾
edit.setSelection(length);
}
@ -676,119 +878,190 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* Should not happen, check for debug
*/
// 如果index大于mEditTextList的子元素数量则输出错误日志
if(index > mEditTextList.getChildCount()) {
Log.e(TAG, "Index out of mEditTextList boundrary, should not happen");
}
// 获取列表项
View view = getListItem(text, index);
// 将列表项添加到mEditTextList中
mEditTextList.addView(view, index);
// 获取NoteEditText
NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
// 设置焦点
edit.requestFocus();
// 设置光标位置
edit.setSelection(0);
// 遍历mEditTextList中的子元素从index+1开始
for (int i = index + 1; i < mEditTextList.getChildCount(); i++) {
// 设置NoteEditText的索引
((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text))
.setIndex(i);
}
}
// 切换到列表模式
private void switchToListMode(String text) {
// 移除所有视图
mEditTextList.removeAllViews();
// 将文本按行分割
String[] items = text.split("\n");
// 初始化索引
int index = 0;
// 遍历每一行
for (String item : items) {
// 如果行不为空
if(!TextUtils.isEmpty(item)) {
// 添加列表项
mEditTextList.addView(getListItem(item, index));
// 索引自增
index++;
}
}
// 添加一个空列表项
mEditTextList.addView(getListItem("", index));
// 获取最后一个列表项的EditText并请求焦点
mEditTextList.getChildAt(index).findViewById(R.id.et_edit_text).requestFocus();
// 隐藏NoteEditor
mNoteEditor.setVisibility(View.GONE);
// 显示EditTextList
mEditTextList.setVisibility(View.VISIBLE);
}
// 根据用户查询结果高亮显示全文
private Spannable getHighlightQueryResult(String fullText, String userQuery) {
// 创建一个SpannableString对象用于存储高亮显示的文本
SpannableString spannable = new SpannableString(fullText == null ? "" : fullText);
// 如果用户查询结果不为空
if (!TextUtils.isEmpty(userQuery)) {
// 创建一个正则表达式对象,用于匹配用户查询结果
mPattern = Pattern.compile(userQuery);
// 创建一个Matcher对象用于匹配全文
Matcher m = mPattern.matcher(fullText);
// 定义一个起始位置
int start = 0;
// 循环匹配全文
while (m.find(start)) {
// 设置高亮显示的背景颜色
spannable.setSpan(
new BackgroundColorSpan(this.getResources().getColor(
R.color.user_query_highlight)), m.start(), m.end(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
// 更新起始位置
start = m.end();
}
}
// 返回高亮显示的文本
return spannable;
}
// 根据传入的item和index获取一个View
private View getListItem(String item, int index) {
// 通过LayoutInflater加载布局文件
View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null);
// 获取EditText
final NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
// 设置EditText的文本样式
edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
// 获取CheckBox
CheckBox cb = ((CheckBox) view.findViewById(R.id.cb_edit_item));
// 设置CheckBox的监听器
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// 如果CheckBox被选中
if (isChecked) {
// 设置EditText的画笔标志添加删除线
edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
} else {
// 设置EditText的画笔标志取消删除线
edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
}
}
});
// 如果item以TAG_CHECKED开头
if (item.startsWith(TAG_CHECKED)) {
// 设置CheckBox为选中状态
cb.setChecked(true);
// 设置EditText的画笔标志添加删除线
edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
// 去掉TAG_CHECKED
item = item.substring(TAG_CHECKED.length(), item.length()).trim();
// 如果item以TAG_UNCHECKED开头
} else if (item.startsWith(TAG_UNCHECKED)) {
// 设置CheckBox为未选中状态
cb.setChecked(false);
// 设置EditText的画笔标志取消删除线
edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
// 去掉TAG_UNCHECKED
item = item.substring(TAG_UNCHECKED.length(), item.length()).trim();
}
// 设置EditText的监听器
edit.setOnTextViewChangeListener(this);
// 设置EditText的索引
edit.setIndex(index);
// 设置EditText的文本
edit.setText(getHighlightQueryResult(item, mUserQuery));
return view;
}
// 当EditText的文本发生变化时调用
public void onTextChange(int index, boolean hasText) {
// 如果索引超出范围
if (index >= mEditTextList.getChildCount()) {
Log.e(TAG, "Wrong index, should not happen");
return;
}
// 如果有文本
if(hasText) {
// 设置CheckBox为可见
mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.VISIBLE);
// 如果没有文本
} else {
// 设置CheckBox为不可见
mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.GONE);
}
}
public void onCheckListModeChanged(int oldMode, int newMode) {
// 如果新模式是检查列表模式
if (newMode == TextNote.MODE_CHECK_LIST) {
// 切换到列表模式
switchToListMode(mNoteEditor.getText().toString());
} else {
// 如果没有获取到工作文本
if (!getWorkingText()) {
mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ",
// 将工作笔记的内容中的未选中标签替换为空字符串
mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ", ""));
""));
}
// 设置笔记编辑器的内容为高亮查询结果
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
// 隐藏文本编辑器列表
mEditTextList.setVisibility(View.GONE);
// 显示笔记编辑器
mNoteEditor.setVisibility(View.VISIBLE);
}
}
// 获取工作文本
private boolean getWorkingText() {
boolean hasChecked = false;
// 如果工作笔记的检查列表模式为检查列表模式
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
// 创建一个StringBuilder对象
StringBuilder sb = new StringBuilder();
// 遍历EditTextList的子视图
for (int i = 0; i < mEditTextList.getChildCount(); i++) {
// 获取子视图
View view = mEditTextList.getChildAt(i);
// 获取NoteEditText对象
NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
// 如果EditText的内容不为空
if (!TextUtils.isEmpty(edit.getText())) {
if (((CheckBox) view.findViewById(R.id.cb_edit_item)).isChecked()) {
sb.append(TAG_CHECKED).append(" ").append(edit.getText()).append("\n");
@ -806,8 +1079,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private boolean saveNote() {
// 获取当前工作文本
getWorkingText();
// 保存当前笔记
boolean saved = mWorkingNote.saveNote();
// 如果保存成功
if (saved) {
/**
* There are two modes from List view to edit view, open one note,
@ -818,6 +1094,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
*/
setResult(RESULT_OK);
}
// 返回保存结果
return saved;
}
@ -856,18 +1133,26 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
}
// 根据传入的content去除TAG_CHECKED和TAG_UNCHECKED标签并返回处理后的字符串
private String makeShortcutIconTitle(String content) {
// 去除TAG_CHECKED标签
content = content.replace(TAG_CHECKED, "");
// 去除TAG_UNCHECKED标签
content = content.replace(TAG_UNCHECKED, "");
// 如果处理后的字符串长度大于SHORTCUT_ICON_TITLE_MAX_LEN则截取前SHORTCUT_ICON_TITLE_MAX_LEN个字符
return content.length() > SHORTCUT_ICON_TITLE_MAX_LEN ? content.substring(0,
SHORTCUT_ICON_TITLE_MAX_LEN) : content;
}
// 显示Toast使用默认时长
private void showToast(int resId) {
// 调用showToast方法传入resId和默认时长
showToast(resId, Toast.LENGTH_SHORT);
}
// 显示Toast使用指定时长
private void showToast(int resId, int duration) {
// 使用Toast.makeText方法创建Toast对象并显示
Toast.makeText(this, resId, duration).show();
}
}

@ -100,18 +100,30 @@ public class NotesListItem extends LinearLayout {
}
private void setBackground(NoteItemData data) {
// 获取背景颜色ID
int id = data.getBgColorId();
// 判断类型
if (data.getType() == Notes.TYPE_NOTE) {
// 判断是否为单条笔记
if (data.isSingle() || data.isOneFollowingFolder()) {
// 设置背景资源为单条笔记背景
setBackgroundResource(NoteItemBgResources.getNoteBgSingleRes(id));
// 判断是否为最后一条笔记
} else if (data.isLast()) {
// 设置背景资源为最后一条笔记背景
setBackgroundResource(NoteItemBgResources.getNoteBgLastRes(id));
// 判断是否为第一条笔记或多个文件夹
} else if (data.isFirst() || data.isMultiFollowingFolder()) {
// 设置背景资源为第一条笔记背景
setBackgroundResource(NoteItemBgResources.getNoteBgFirstRes(id));
// 其他情况
} else {
// 设置背景资源为普通笔记背景
setBackgroundResource(NoteItemBgResources.getNoteBgNormalRes(id));
}
// 如果为文件夹
} else {
// 设置背景资源为文件夹背景
setBackgroundResource(NoteItemBgResources.getFolderBgRes());
}
}

Loading…
Cancel
Save