diff --git a/src/net/micode/notes/ui/AlarmAlertActivity.java b/src/net/micode/notes/ui/AlarmAlertActivity.java index b3bb7f6..0b9a91a 100644 --- a/src/net/micode/notes/ui/AlarmAlertActivity.java +++ b/src/net/micode/notes/ui/AlarmAlertActivity.java @@ -43,8 +43,8 @@ import java.io.IOException; public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener { private long mNoteId; //文本在数据存储中的ID号 private String mSnippet; //闹钟提示时出现的文本片段 - private static final int SNIPPET_PREW_MAX_LEN = 60; - MediaPlayer mPlayer; + private static final int SNIPPET_PREW_MAX_LEN = 60; //闹钟提示对话框中的便签片段的最大长度 + MediaPlayer mPlayer; //用于播放闹钟音效的MediaPlayer对象 @Override protected void onCreate(Bundle savedInstanceState) { @@ -52,9 +52,10 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD //Bundle 类型的数据与 Map类型的数据相似,都是以keu-value的形式存储数据的 //on save InstanceState方法是用来保存Activity的状态的 //能从onCreate的参数savedInsanceState中获得状态数据 + //不显示窗口标题 requestWindowFeature(Window.FEATURE_NO_TITLE); - //界面显示-无标题 + //获取当前窗口的Window实例,用于设置标志以在屏幕锁定时显示此Activity final Window win = getWindow(); win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); @@ -70,6 +71,7 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD Intent intent = getIntent(); + //从Intent的data中提取闹钟ID(mNoteId)和文本片段(mSnippet) try { mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1)); mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId); @@ -80,6 +82,7 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD : mSnippet; //判读标签片段是否达到符合长度 } catch (IllegalArgumentException e) { + //数据不合法,捕获异常并返回 e.printStackTrace(); return; } @@ -105,22 +108,28 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD } } + //判断屏幕是否亮起 private boolean isScreenOn() { PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); return pm.isScreenOn(); } + //播放默认的闹钟声音 private void playAlarmSound() { + //获取系统默认的闹钟声音URI Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM); + //获取当前系统设置的闹钟流是否受静音模式影响 int silentModeStreams = Settings.System.getInt(getContentResolver(), Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); + //如果闹钟声音在当前系统设置中受静音模式影响,则将其设置到相应的音频流 if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) { mPlayer.setAudioStreamType(silentModeStreams); } else { mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM); } + //尝试设置数据源,准备播放器,设置为循环播放,并开始播放 try { mPlayer.setDataSource(this, url); mPlayer.prepare(); @@ -137,22 +146,28 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block - e.printStackTrace(); + e.printStackTrace(); //捕捉到异常,输出堆栈跟踪信息并不做进一步处理 } } + //显示操作对话框,让用户能够选择停止闹钟或查看便签 private void showActionDialog() { AlertDialog.Builder dialog = new AlertDialog.Builder(this); + //设置对话框标题和消息,并提供一个"确定"按钮 dialog.setTitle(R.string.app_name); dialog.setMessage(mSnippet); dialog.setPositiveButton(R.string.notealert_ok, this); + //如果屏幕已经亮起,则提供一个"查看"按钮 if (isScreenOn()) { dialog.setNegativeButton(R.string.notealert_enter, this); } + //显示对话框,并设置监听器监听对话框消失事件 dialog.show().setOnDismissListener(this); } + //当用户点击对话框按钮时调用这个方法 public void onClick(DialogInterface dialog, int which) { + //如果点击了"查看"按钮,启动NoteEditActivity来查看并编辑便签 switch (which) { case DialogInterface.BUTTON_NEGATIVE: Intent intent = new Intent(this, NoteEditActivity.class); @@ -165,11 +180,13 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD } } + //当对话框消失时,停止播放声音并结束此活动 public void onDismiss(DialogInterface dialog) { stopAlarmSound(); finish(); } + //停止并释放MediaPlayer资源 private void stopAlarmSound() { if (mPlayer != null) { mPlayer.stop(); diff --git a/src/net/micode/notes/ui/AlarmInitReceiver.java b/src/net/micode/notes/ui/AlarmInitReceiver.java index f221202..4a38bec 100644 --- a/src/net/micode/notes/ui/AlarmInitReceiver.java +++ b/src/net/micode/notes/ui/AlarmInitReceiver.java @@ -28,38 +28,50 @@ import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; +//AlarmInitReceiver 类继承自BroadcastReceiver, 广播接收者用于获取系统启动或其他特定事件的通知 public class AlarmInitReceiver extends BroadcastReceiver { + //数据库查询的列名数组,只查询ID和提醒日期 private static final String [] PROJECTION = new String [] { - NoteColumns.ID, - NoteColumns.ALERTED_DATE + NoteColumns.ID, //便签的ID + NoteColumns.ALERTED_DATE //便签的提醒日期 }; + //定义两个静态常量,代表数据表列索引ID和提醒日期 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, + //通过内容解析器查询便签,寻找提醒时间大于当前时间且类型为TYPE_NOTE的便签 + Cursor c = context.getContentResolver().query(Notes.CONTENT_NOTE_URI, // CONTENT_NOTE_URI是访问便签数据的URI PROJECTION, NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE, new String[] { String.valueOf(currentDate) }, null); + //遍历查询出的结果 if (c != null) { - if (c.moveToFirst()) { + if (c.moveToFirst()) { //移动游标到第一条记录 do { + //读取提醒日期时间 long alertDate = c.getLong(COLUMN_ALERTED_DATE); + //创建指向AlarmReceiver的Intent Intent sender = new Intent(context, AlarmReceiver.class); 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); + //使用AlarmManager设置一个闹钟,当系统时间达到提醒日期时触发广播 alermManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent); - } while (c.moveToNext()); + } while (c.moveToNext()); //移动到下一条记录 } - c.close(); + c.close(); //关闭游标 } } } diff --git a/src/net/micode/notes/ui/AlarmReceiver.java b/src/net/micode/notes/ui/AlarmReceiver.java index 54e503b..536e72a 100644 --- a/src/net/micode/notes/ui/AlarmReceiver.java +++ b/src/net/micode/notes/ui/AlarmReceiver.java @@ -20,11 +20,16 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +//AlarmReceiver 类继承自 BroadcastReceiver, 广播接收者用于获取系统启动或其他特定事件的通知 public class AlarmReceiver extends BroadcastReceiver { + //当广播被执行时执行此方法 @Override public void onReceive(Context context, Intent intent) { + //设置Intent的目标Activity为AlarmAlertActivity intent.setClass(context, AlarmAlertActivity.class); + //添加FLAG_ACTIVITY_NEW_TASK标志,用于启动一个新的任务栈 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + //启动目标Activity,AlarmAlertActivity context.startActivity(intent); } } diff --git a/src/net/micode/notes/ui/DateTimePicker.java b/src/net/micode/notes/ui/DateTimePicker.java index 496b0cd..f85e31c 100644 --- a/src/net/micode/notes/ui/DateTimePicker.java +++ b/src/net/micode/notes/ui/DateTimePicker.java @@ -28,42 +28,67 @@ import android.view.View; import android.widget.FrameLayout; import android.widget.NumberPicker; +//自定义的日期时间选择器控件,继承自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; + + //根据一周的天数设置日期选择器(NumberPicker)的最大和最小值 private static final int DATE_SPINNER_MIN_VAL = 0; private static final int DATE_SPINNER_MAX_VAL = DAYS_IN_ALL_WEEK - 1; + + //定义24小时视图中小时选择器的最大和最小值 private static final int HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW = 0; private static final int HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW = 23; + + //定义12小时视图中小时选择器的最大和最小值 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; + + //AM/PM 选择器的最大和最小值 private static final int AMPM_SPINNER_MIN_VAL = 0; private static final int AMPM_SPINNER_MAX_VAL = 1; + //NumberPicker 控件的实例引用 private final NumberPicker mDateSpinner; private final NumberPicker mHourSpinner; private final NumberPicker mMinuteSpinner; private final NumberPicker mAmPmSpinner; + + //用于存储和处理日期的Calendar实例 private Calendar mDate; + //日期显示的数据,用于存储一周内每一天的描述 private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK]; + //是否为上午的变量 private boolean mIsAm; + //是否为24小时视图的标志变量 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) { @@ -73,6 +98,7 @@ public class DateTimePicker extends FrameLayout { } }; + //小时改变监听器 private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() { @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { @@ -115,6 +141,7 @@ public class DateTimePicker extends FrameLayout { } }; + //分钟改变监听器 private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() { @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { @@ -144,6 +171,7 @@ public class DateTimePicker extends FrameLayout { } }; + //AM/PM 改变监听器 private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() { @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { @@ -158,24 +186,30 @@ public class DateTimePicker extends FrameLayout { } }; + //日期时间变化的监听器接口,需要被实现来响应日期时间的任何变化 public interface OnDateTimeChangedListener { void onDateTimeChanged(DateTimePicker view, int year, int month, int dayOfMonth, int hourOfDay, int minute); } + //构造器1:当没有指定日期时,默认使用当前的系统时间 public DateTimePicker(Context context) { this(context, System.currentTimeMillis()); } + //构造器2:允许在创建控件时指定一个日期 public DateTimePicker(Context context, long date) { this(context, date, DateFormat.is24HourFormat(context)); } + //构造器3:最完整的构造器,允许指定日期和是否以24小时格式显示时间 public DateTimePicker(Context context, long date, boolean is24HourView) { - super(context); - mDate = Calendar.getInstance(); - mInitialising = true; + super(context); //调用父类构造器 + mDate = Calendar.getInstance(); //初始化当前日期和时间的日历实例 + mInitialising = true; //开始初始化流程的标志 + //设置是否用上午/下午模式还是24小时制 mIsAm = getCurrentHourOfDay() >= HOURS_IN_HALF_DAY; + //通过XML布局文件创建视图 inflate(context, R.layout.datetime_picker, this); mDateSpinner = (NumberPicker) findViewById(R.id.date); @@ -203,17 +237,20 @@ public class DateTimePicker extends FrameLayout { updateHourControl(); updateAmPmControl(); + //更新24小时播放视图 set24HourView(is24HourView); - // set to current time + // set to current time设置当前日期到指定的时间 setCurrentDate(date); + //更新控件的启用状态 setEnabled(isEnabled()); - // set the content descriptions - mInitialising = false; + // set the content descriptions 设置内容描述 + mInitialising = false; //初始化完成 } + //设置控件是否可用,并且使内部的NumberPicker控件与之匹配 @Override public void setEnabled(boolean enabled) { if (mIsEnabled == enabled) { @@ -227,6 +264,7 @@ public class DateTimePicker extends FrameLayout { mIsEnabled = enabled; } + //检查控件是否可以与用户交互 @Override public boolean isEnabled() { return mIsEnabled; @@ -237,6 +275,8 @@ public class DateTimePicker extends FrameLayout { * * @return the current date in millis */ + + //获取当前的日期及时间 public long getCurrentDateInTimeMillis() { return mDate.getTimeInMillis(); } @@ -246,6 +286,8 @@ public class DateTimePicker extends FrameLayout { * * @param date The current date in millis */ + + //设置当前日期和时间 public void setCurrentDate(long date) { Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(date); @@ -262,6 +304,8 @@ public class DateTimePicker extends FrameLayout { * @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); @@ -276,6 +320,8 @@ public class DateTimePicker extends FrameLayout { * * @return The current year */ + + //获取和设置当前的年份 public int getCurrentYear() { return mDate.get(Calendar.YEAR); } @@ -299,6 +345,8 @@ public class DateTimePicker extends FrameLayout { * * @return The current month in the year */ + + //获取和设置当前的月份 public int getCurrentMonth() { return mDate.get(Calendar.MONTH); } @@ -322,6 +370,8 @@ public class DateTimePicker extends FrameLayout { * * @return The day of the month */ + + //获取和设置当前的日期(天) public int getCurrentDay() { return mDate.get(Calendar.DAY_OF_MONTH); } @@ -344,6 +394,8 @@ 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 */ + + //获取和设置当前的小时(24时制) public int getCurrentHourOfDay() { return mDate.get(Calendar.HOUR_OF_DAY); } @@ -394,6 +446,8 @@ public class DateTimePicker extends FrameLayout { * * @return The Current Minute */ + + //获取和设置当前的分钟数 public int getCurrentMinute() { return mDate.get(Calendar.MINUTE); } @@ -413,6 +467,8 @@ public class DateTimePicker extends FrameLayout { /** * @return true if this is in 24 hour view else false. */ + + //判断是否为24小时格式 public boolean is24HourView () { return mIs24HourView; } @@ -422,6 +478,8 @@ public class DateTimePicker extends FrameLayout { * * @param is24HourView True for 24 hour mode. False for AM/PM mode. */ + + //设置为24小时格式或者 AM/PM格式 public void set24HourView(boolean is24HourView) { if (mIs24HourView == is24HourView) { return; @@ -434,37 +492,40 @@ public class DateTimePicker extends FrameLayout { 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); + 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); + 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(); + mDateSpinner.setDisplayedValues(mDateDisplayValues); //设置日期选择器显示值为新的日期列表 + mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2); //设置选择器的当前值为中间的日期 + mDateSpinner.invalidate(); //刷新视图状态 } + //更新AM/PM显示控制,以显示或隐藏AM/PM选择器,具体取决于是否采用24小时视图 private void updateAmPmControl() { if (mIs24HourView) { - mAmPmSpinner.setVisibility(View.GONE); + mAmPmSpinner.setVisibility(View.GONE); //如果是24小时制,则隐藏AM/PM选择器 } else { - int index = mIsAm ? Calendar.AM : Calendar.PM; - mAmPmSpinner.setValue(index); - mAmPmSpinner.setVisibility(View.VISIBLE); + int index = mIsAm ? Calendar.AM : Calendar.PM; //确定当前是上午还是下午 + mAmPmSpinner.setValue(index); //设置AM/PM选择器值为当前AM或者PM + mAmPmSpinner.setVisibility(View.VISIBLE); //显示AM/PM选择器 } } + //更新小时显示控制,调整小时选择器的最小和最大值,以匹配所选择的24小时制或12小时制 private void updateHourControl() { if (mIs24HourView) { - mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW); - mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW); + mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW); //如果24,则小时选择器最小值设置为0/1 + mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW); //小时选择器的最大值设置为23/24 } else { - mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW); - mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW); + mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW); // 如果12,小时选择器的最小值 1 + mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW); // 小时选择器的最大值 12 } } @@ -472,14 +533,17 @@ 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; + mOnDateTimeChangedListener = callback; //赋值回调接口 } + //调用回调函数,当日期或者时间发生改变时,这个方法通知订阅了监听器的客户端 private void onDateTimeChanged() { if (mOnDateTimeChangedListener != null) { mOnDateTimeChangedListener.onDateTimeChanged(this, getCurrentYear(), - getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute()); + getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute()); //传递更新后的值给监听器 } } } diff --git a/src/net/micode/notes/ui/DateTimePickerDialog.java b/src/net/micode/notes/ui/DateTimePickerDialog.java index 2c47ba4..d7ef4fc 100644 --- a/src/net/micode/notes/ui/DateTimePickerDialog.java +++ b/src/net/micode/notes/ui/DateTimePickerDialog.java @@ -29,61 +29,75 @@ import android.content.DialogInterface.OnClickListener; import android.text.format.DateFormat; import android.text.format.DateUtils; +//继承自 AlertDialog,包含日期和时间选择的功能 public class DateTimePickerDialog extends AlertDialog implements OnClickListener { + //用于存储当前选择日期和时间 private Calendar mDate = Calendar.getInstance(); + //标记是否使用24小时视图展示时间 private boolean mIs24HourView; + //回调接口定义,当日期和时间设定后激活 private OnDateTimeSetListener mOnDateTimeSetListener; + //本对话框包含的日期和时间选择器视图 private DateTimePicker mDateTimePicker; - + //定义回调接口,用于通知调用者日期和时间已经设定 public interface OnDateTimeSetListener { void OnDateTimeSet(AlertDialog dialog, long date); } + //DateTimePickerDialog构造函数 public DateTimePickerDialog(Context context, long date) { - super(context); - mDateTimePicker = new DateTimePicker(context); - setView(mDateTimePicker); + super(context); //调用AlertDiaglog构造函数 + mDateTimePicker = new DateTimePicker(context);//创建一个新的DateTimePicker实例 + setView(mDateTimePicker);//将DateTimePicker视图添加到对话框中 + //注册一个回调,以在日期和时间改变时更新内部的Calendar实例 mDateTimePicker.setOnDateTimeChangedListener(new OnDateTimeChangedListener() { public void onDateTimeChanged(DateTimePicker view, int year, int month, int dayOfMonth, int hourOfDay, int minute) { + //更新Calendar实例的年、月、日、时、分 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()); + updateTitle(mDate.getTimeInMillis()); //更新对话框标题显示的日期 } }); - mDate.setTimeInMillis(date); - mDate.set(Calendar.SECOND, 0); - mDateTimePicker.setCurrentDate(mDate.getTimeInMillis()); + mDate.setTimeInMillis(date); // 将对话框初始化为传入的日期和时间值 + mDate.set(Calendar.SECOND, 0); // 秒字段设为0 + mDateTimePicker.setCurrentDate(mDate.getTimeInMillis()); // 将DateTimePicker初始化到当前日期 + //设置对话框的'确定'和'取消'按钮 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()); + updateTitle(mDate.getTimeInMillis()); // 初始对话框标题显示的日期和时间 } + //设置时间是否显示为24小时视图 public void set24HourView(boolean is24HourView) { mIs24HourView = is24HourView; } + //设置DateTimeSet监听回调 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; flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR; - setTitle(DateUtils.formatDateTime(this.getContext(), date, flag)); + setTitle(DateUtils.formatDateTime(this.getContext(), date, flag)); // 格式化时间并设置标题 } + //点击对话框按钮调用,通知监听者时间已设置 public void onClick(DialogInterface arg0, int arg1) { if (mOnDateTimeSetListener != null) { - mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis()); + mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis()); // 激活回调传递当前设置的日期和时间 } } diff --git a/src/net/micode/notes/ui/NoteEditText.java b/src/net/micode/notes/ui/NoteEditText.java index c607352..07060b5 100644 --- a/src/net/micode/notes/ui/NoteEditText.java +++ b/src/net/micode/notes/ui/NoteEditText.java @@ -189,7 +189,7 @@ public class NoteEditText extends EditText { mOnTextViewChangeListener.onTextChange(mIndex, false); } else { mOnTextViewChangeListener.onTextChange(mIndex, true); - } + }9 } super.onFocusChanged(focused, direction, previouslyFocusedRect); } @@ -197,37 +197,43 @@ public class NoteEditText extends EditText { //上下文菜单创建时的处理,可以在编辑框中添加特定行为的菜单项,例如打电话、打开网页或发送邮箱 @Override protected void onCreateContextMenu(ContextMenu menu) { + //检查文本内容是否为Spanned类型 if (getText() instanceof Spanned) { - int selStart = getSelectionStart(); - int selEnd = getSelectionEnd(); + int selStart = getSelectionStart();//获取选择文本起始位置 + int selEnd = getSelectionEnd();// 结束位置 int min = Math.min(selStart, selEnd); int max = Math.max(selStart, selEnd); + //从选择文本中获取URLSpan对象数组 final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class); + //如果只有一个URLSpan存在 if (urls.length == 1) { int defaultResId = 0; + //遍历所有已定义的模式(schema) for(String schema: sSchemaActionResMap.keySet()) { + //如果URLSpan的URL中包含该模式 if(urls[0].getURL().indexOf(schema) >= 0) { + //获取该模式对应的资源ID defaultResId = sSchemaActionResMap.get(schema); break; } } - + //如果没有找到匹配的模式对应的资源ID,则使用R.string.note_link_other作为默认资源ID if (defaultResId == 0) { defaultResId = R.string.note_link_other; } - + //像上下文菜单中添加菜单项,并设置点击事件 menu.add(0, 0, 0, defaultResId).setOnMenuItemClickListener( new OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { - // goto a new intent + // goto a new intent 执行URLSpan中定义的点击操作 urls[0].onClick(NoteEditText.this); return true; } }); } } - super.onCreateContextMenu(menu); + super.onCreateContextMenu(menu); //调用父类的方法创建上下文菜单 } }