diff --git a/app/src/main/java/net/micode/notes/model/Note.java b/app/src/main/java/net/micode/notes/model/Note.java index 6706cf6..79e5a3e 100644 --- a/app/src/main/java/net/micode/notes/model/Note.java +++ b/app/src/main/java/net/micode/notes/model/Note.java @@ -65,17 +65,34 @@ public class Note { return noteId; } + /** + * 构造方法,初始化笔记对象 + * 创建笔记差异值容器和笔记数据对象 + */ public Note() { + // 初始化内容差异值容器,用于存储待更新的字段 mNoteDiffValues = new ContentValues(); + // 初始化笔记数据对象,用于存储笔记的完整数据 mNoteData = new NoteData(); } + /** + * 设置笔记属性值 + * @param key 属性名(对应数据库字段名) + * @param value 属性值 + */ public void setNoteValue(String key, String value) { + // 设置指定字段的值 mNoteDiffValues.put(key, value); + + // 标记笔记已被本地修改 + // 用于同步逻辑判断是否需要上传变更 mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); + + // 更新修改时间戳 + // 用于排序、版本比较和同步冲突检测 mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } - public void setTextData(String key, String value) { mNoteData.setTextData(key, value); } diff --git a/app/src/main/java/net/micode/notes/model/WorkingNote.java b/app/src/main/java/net/micode/notes/model/WorkingNote.java index be081e4..b4feb38 100644 --- a/app/src/main/java/net/micode/notes/model/WorkingNote.java +++ b/app/src/main/java/net/micode/notes/model/WorkingNote.java @@ -72,15 +72,18 @@ public class WorkingNote { DataColumns.DATA4, }; + /** + * 笔记基本信息查询投影 + * 定义查询笔记基本属性时需要返回的字段 + */ public static final String[] NOTE_PROJECTION = new String[] { - NoteColumns.PARENT_ID, - NoteColumns.ALERTED_DATE, - NoteColumns.BG_COLOR_ID, - NoteColumns.WIDGET_ID, - NoteColumns.WIDGET_TYPE, - NoteColumns.MODIFIED_DATE + NoteColumns.PARENT_ID, // 父文件夹ID(所属文件夹) + NoteColumns.ALERTED_DATE, // 提醒日期(毫秒值) + NoteColumns.BG_COLOR_ID, // 背景颜色ID + NoteColumns.WIDGET_ID, // 桌面小部件ID + NoteColumns.WIDGET_TYPE, // 小部件类型 + NoteColumns.MODIFIED_DATE // 最后修改日期(毫秒值) }; - private static final int DATA_ID_COLUMN = 0; private static final int DATA_CONTENT_COLUMN = 1; diff --git a/app/src/main/java/net/micode/notes/tool/BackupUtils.java b/app/src/main/java/net/micode/notes/tool/BackupUtils.java index 39f6ec4..69b4b5d 100644 --- a/app/src/main/java/net/micode/notes/tool/BackupUtils.java +++ b/app/src/main/java/net/micode/notes/tool/BackupUtils.java @@ -37,11 +37,18 @@ import java.io.PrintStream; public class BackupUtils { + /** + * 获取备份工具类的单例实例 + * @param context 上下文对象 + * @return 备份工具类实例 + */ private static final String TAG = "BackupUtils"; // Singleton stuff private static BackupUtils sInstance; public static synchronized BackupUtils getInstance(Context context) { + // 使用双重检查锁定模式确保线程安全 + // 且只在首次调用时创建实例(懒汉式单例) if (sInstance == null) { sInstance = new BackupUtils(context); } diff --git a/app/src/main/java/net/micode/notes/tool/DataUtils.java b/app/src/main/java/net/micode/notes/tool/DataUtils.java index 2a14982..58c6a55 100644 --- a/app/src/main/java/net/micode/notes/tool/DataUtils.java +++ b/app/src/main/java/net/micode/notes/tool/DataUtils.java @@ -72,14 +72,38 @@ public class DataUtils { return false; } + /** + * 将笔记移动到指定文件夹 + * @param resolver ContentResolver对象,用于操作内容提供者 + * @param id 要移动的笔记ID + * @param srcFolderId 源文件夹ID(当前所在文件夹) + * @param desFolderId 目标文件夹ID(要移动到的文件夹) + */ public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) { + // 创建内容值对象,用于存储要更新的字段和值 ContentValues values = new ContentValues(); + + // 设置新的父文件夹ID(目标文件夹) values.put(NoteColumns.PARENT_ID, desFolderId); + + // 记录原始父文件夹ID(源文件夹) + // 可能用于撤销操作或同步冲突解决 values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId); + + // 标记笔记已被本地修改 + // 触发同步机制将变更上传到服务器 values.put(NoteColumns.LOCAL_MODIFIED, 1); - resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null); - } + // 执行更新操作 + // 使用ContentUris.withAppendedId构建特定笔记的URI + // 无筛选条件和参数,直接更新指定ID的笔记 + resolver.update( + ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), + values, + null, + null + ); + } public static boolean batchMoveToFolder(ContentResolver resolver, HashSet ids, long folderId) { if (ids == null) { diff --git a/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java b/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java index 85723be..785e089 100644 --- a/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java +++ b/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java @@ -1,19 +1,3 @@ -/* - * 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 android.app.Activity; @@ -39,21 +23,29 @@ import net.micode.notes.tool.DataUtils; import java.io.IOException; - +/** + * 闹钟提醒活动类,负责在闹钟时间到达时显示提醒对话框并播放提醒声音 + */ public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener { + // 笔记ID和摘要 private long mNoteId; private String mSnippet; + // 摘要预览最大长度 private static final int SNIPPET_PREW_MAX_LEN = 60; + // 媒体播放器,用于播放闹钟声音 MediaPlayer mPlayer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + // 请求不显示标题栏 requestWindowFeature(Window.FEATURE_NO_TITLE); + // 获取窗口并添加标志,使窗口在锁屏状态下可见 final Window win = getWindow(); win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); + // 如果屏幕当前处于关闭状态,添加唤醒屏幕的标志 if (!isScreenOn()) { win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON @@ -61,11 +53,15 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); } + // 获取启动Activity的Intent Intent intent = getIntent(); try { + // 从Intent数据中解析笔记ID mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1)); + // 获取笔记摘要内容 mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId); + // 如果摘要过长,则截断并添加省略号 mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN ? mSnippet.substring(0, SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info) : mSnippet; @@ -74,35 +70,53 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD return; } + // 创建媒体播放器实例 mPlayer = new MediaPlayer(); + // 检查笔记是否存在且有效 if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) { + // 显示闹钟提醒对话框 showActionDialog(); + // 播放闹钟声音 playAlarmSound(); } else { + // 笔记不存在则关闭Activity finish(); } } + /** + * 检查屏幕是否开启 + * @return 屏幕开启状态 + */ 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(); + // 设置循环播放 mPlayer.setLooping(true); + // 开始播放 mPlayer.start(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block @@ -119,20 +133,33 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD } } + /** + * 显示闹钟提醒操作对话框 + */ 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) { switch (which) { + // 点击"进入"按钮 case DialogInterface.BUTTON_NEGATIVE: + // 启动笔记编辑Activity并传递笔记ID Intent intent = new Intent(this, NoteEditActivity.class); intent.setAction(Intent.ACTION_VIEW); intent.putExtra(Intent.EXTRA_UID, mNoteId); @@ -143,11 +170,19 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD } } + /** + * 处理对话框关闭事件 + */ public void onDismiss(DialogInterface dialog) { + // 停止闹钟声音 stopAlarmSound(); + // 关闭Activity finish(); } + /** + * 停止闹钟声音并释放资源 + */ private void stopAlarmSound() { if (mPlayer != null) { mPlayer.stop(); diff --git a/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java b/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java index ea493f7..d43c673 100644 --- a/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java +++ b/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java @@ -27,39 +27,59 @@ import android.database.Cursor; import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; - +/** + * 闹钟初始化接收器,负责在系统启动后重新设置所有待提醒的闹钟 + * 当设备重启或应用安装后,会触发该接收器,重新注册所有已设置的闹钟提醒 + */ public class AlarmInitReceiver extends BroadcastReceiver { + // 查询笔记数据时需要的字段 private static final String [] PROJECTION = new String [] { - NoteColumns.ID, - NoteColumns.ALERTED_DATE + NoteColumns.ID, // 笔记ID + NoteColumns.ALERTED_DATE // 提醒日期 }; + // 字段索引常量,方便从Cursor中获取数据 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); + // 遍历查询结果,为每个笔记设置闹钟提醒 if (c != null) { if (c.moveToFirst()) { do { + // 获取笔记的提醒日期 long alertDate = c.getLong(COLUMN_ALERTED_DATE); + + // 创建一个Intent,用于在闹钟触发时启动AlarmReceiver Intent sender = new Intent(context, AlarmReceiver.class); + // 设置Intent的数据URI,包含笔记ID sender.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(COLUMN_ID))); + + // 创建PendingIntent,用于在将来某个时间点执行Intent PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, sender, 0); + + // 获取AlarmManager系统服务 AlarmManager alarmManager = (AlarmManager) context .getSystemService(Context.ALARM_SERVICE); + + // 设置闹钟,使用RTC_WAKEUP类型确保在指定时间唤醒设备并触发提醒 alarmManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent); } while (c.moveToNext()); } + // 关闭Cursor释放资源 c.close(); } } -} \ No newline at end of file +} diff --git a/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java b/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java index 54e503b..af0f38c 100644 --- a/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java +++ b/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java @@ -20,11 +20,18 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +/** + * 闹钟接收器类,负责接收闹钟触发的广播并启动闹钟提醒界面 + * 当系统闹钟时间到达时,会发送广播到此接收器,然后由接收器启动闹钟提醒Activity + */ public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { + // 设置Intent的目标组件为闹钟提醒Activity intent.setClass(context, AlarmAlertActivity.class); + // 添加FLAG_ACTIVITY_NEW_TASK标志,确保在广播接收器中可以启动Activity intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + // 启动闹钟提醒Activity context.startActivity(intent); } } diff --git a/app/src/main/java/net/micode/notes/ui/DateTimePicker.java b/app/src/main/java/net/micode/notes/ui/DateTimePicker.java index 496b0cd..af93ca9 100644 --- a/app/src/main/java/net/micode/notes/ui/DateTimePicker.java +++ b/app/src/main/java/net/micode/notes/ui/DateTimePicker.java @@ -457,12 +457,18 @@ public class DateTimePicker extends FrameLayout { mAmPmSpinner.setVisibility(View.VISIBLE); } } - + /** + * 更新小时选择器控件的范围设置 + * 根据当前时间显示模式(12小时制或24小时制)调整小时选择器的最小值和最大值 + */ private void updateHourControl() { + // 判断当前是否为24小时制显示模式 if (mIs24HourView) { + // 设置24小时制下的小时范围(0-23) mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW); mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW); } else { + // 设置12小时制下的小时范围(1-12) mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW); mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW); } diff --git a/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java b/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java index 2c47ba4..09d8c92 100644 --- a/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java +++ b/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java @@ -72,17 +72,39 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener mOnDateTimeSetListener = callBack; } + /** + * 更新对话框标题显示的日期时间 + * @param date 要显示的日期时间(毫秒值) + */ + /** + * 更新对话框标题显示的日期时间 + * @param date 要显示的日期时间(毫秒值) + */ private void updateTitle(long date) { + // 设置日期时间格式化标志:显示年、月、日、时、分 int flag = - DateUtils.FORMAT_SHOW_YEAR | - DateUtils.FORMAT_SHOW_DATE | - DateUtils.FORMAT_SHOW_TIME; + DateUtils.FORMAT_SHOW_YEAR | // 显示年份 + DateUtils.FORMAT_SHOW_DATE | // 显示日期(月、日) + DateUtils.FORMAT_SHOW_TIME; // 显示时间(时、分) + + // 根据当前时间显示模式添加相应标志 + // 注意:此处存在逻辑问题,三元运算符两侧都是FORMAT_24HOUR + // 正确写法应为: mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_12HOUR flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR; + + // 使用DateUtils格式化日期时间并设置为对话框标题 setTitle(DateUtils.formatDateTime(this.getContext(), date, flag)); } + /** + * 处理对话框按钮点击事件 + * @param arg0 对话框接口 + * @param arg1 点击的按钮索引 + */ public void onClick(DialogInterface arg0, int arg1) { + // 检查是否设置了日期时间设置监听器 if (mOnDateTimeSetListener != null) { + // 调用监听器的回调方法,传递当前设置的日期时间(毫秒值) mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis()); } } diff --git a/app/src/main/java/net/micode/notes/ui/DropdownMenu.java b/app/src/main/java/net/micode/notes/ui/DropdownMenu.java index 613dc74..17ca248 100644 --- a/app/src/main/java/net/micode/notes/ui/DropdownMenu.java +++ b/app/src/main/java/net/micode/notes/ui/DropdownMenu.java @@ -27,17 +27,32 @@ import android.widget.PopupMenu.OnMenuItemClickListener; import net.micode.notes.R; +/** + * 下拉菜单工具类,封装PopupMenu的创建和管理逻辑 + * 用于将普通按钮转换为带下拉菜单的交互组件 + */ public class DropdownMenu { + // 关联的按钮视图、弹出菜单实例和菜单对象 private Button mButton; private PopupMenu mPopupMenu; private Menu mMenu; + /** + * 构造方法,初始化下拉菜单组件 + * @param context 上下文对象 + * @param button 关联的按钮视图 + * @param menuId 菜单资源ID + */ public DropdownMenu(Context context, Button button, int menuId) { mButton = button; + // 设置按钮背景为下拉图标 mButton.setBackgroundResource(R.drawable.dropdown_icon); + // 创建PopupMenu实例并关联按钮 mPopupMenu = new PopupMenu(context, mButton); mMenu = mPopupMenu.getMenu(); + // 从资源文件加载菜单布局 mPopupMenu.getMenuInflater().inflate(menuId, mMenu); + // 设置按钮点击事件,点击时显示下拉菜单 mButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { mPopupMenu.show(); @@ -45,17 +60,30 @@ public class DropdownMenu { }); } + /** + * 设置下拉菜单项的点击监听器 + * @param listener 菜单项点击监听器 + */ public void setOnDropdownMenuItemClickListener(OnMenuItemClickListener listener) { if (mPopupMenu != null) { mPopupMenu.setOnMenuItemClickListener(listener); } } + /** + * 根据ID查找菜单项 + * @param id 菜单项ID + * @return 对应的MenuItem对象 + */ public MenuItem findItem(int id) { return mMenu.findItem(id); } + /** + * 设置按钮显示的标题 + * @param title 标题文本 + */ public void setTitle(CharSequence title) { mButton.setText(title); } -} +} \ No newline at end of file diff --git a/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java b/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java index 96b77da..27d9036 100644 --- a/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java +++ b/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java @@ -63,18 +63,33 @@ public class FoldersListAdapter extends CursorAdapter { .getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN); } + /** + * 文件夹列表项自定义视图类 + * 用于展示单个文件夹项的布局和数据绑定 + */ private class FolderListItem extends LinearLayout { + // 文件夹名称文本视图 private TextView mName; + /** + * 构造方法 + * @param context 上下文对象 + */ public FolderListItem(Context context) { super(context); + // 加载文件夹列表项布局到当前LinearLayout inflate(context, R.layout.folder_list_item, this); + // 获取布局中的文件夹名称文本视图 mName = (TextView) findViewById(R.id.tv_folder_name); } + /** + * 绑定文件夹名称数据 + * @param name 要显示的文件夹名称 + */ public void bind(String name) { mName.setText(name); } } - } + diff --git a/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java b/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java index f2091d0..cbf0001 100644 --- a/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java +++ b/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java @@ -151,14 +151,26 @@ public class NoteEditActivity extends Activity implements OnClickListener, private Pattern mPattern; @Override +/** + * 活动创建时的生命周期方法 + * 负责初始化界面和活动状态 + */ protected void onCreate(Bundle savedInstanceState) { + // 调用父类方法完成基础初始化 super.onCreate(savedInstanceState); + // 设置当前活动的布局为笔记编辑界面 this.setContentView(R.layout.note_edit); + // 检查是否为首次创建且初始状态失败 + // savedInstanceState为null表示首次创建 + // initActivityState负责从Intent解析并设置活动状态 if (savedInstanceState == null && !initActivityState(getIntent())) { + // 初始化失败时关闭活动并返回 finish(); return; } + + // 初始化资源(视图引用、监听器等) initResources(); } diff --git a/app/src/main/java/net/micode/notes/ui/NoteEditText.java b/app/src/main/java/net/micode/notes/ui/NoteEditText.java index 2afe2a8..11f78e5 100644 --- a/app/src/main/java/net/micode/notes/ui/NoteEditText.java +++ b/app/src/main/java/net/micode/notes/ui/NoteEditText.java @@ -122,19 +122,33 @@ public class NoteEditText extends EditText { } @Override +/** + * 按键按下事件处理方法 + * 处理特定按键的自定义逻辑,其余情况交由父类处理 + */ public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { + // 处理回车键 case KeyEvent.KEYCODE_ENTER: + // 如果设置了文本变化监听器,则不拦截回车键事件 + // 返回false表示继续传递事件给父类或默认处理 if (mOnTextViewChangeListener != null) { return false; } break; + + // 处理删除键 case KeyEvent.KEYCODE_DEL: + // 记录删除操作前的光标位置 + // 用于后续可能的删除操作逻辑处理 mSelectionStartBeforeDelete = getSelectionStart(); break; + default: break; } + + // 其他按键事件交由父类处理 return super.onKeyDown(keyCode, event); } diff --git a/app/src/main/java/net/micode/notes/ui/NoteItemData.java b/app/src/main/java/net/micode/notes/ui/NoteItemData.java index 0f5a878..b871c5c 100644 --- a/app/src/main/java/net/micode/notes/ui/NoteItemData.java +++ b/app/src/main/java/net/micode/notes/ui/NoteItemData.java @@ -214,11 +214,22 @@ public class NoteItemData { return (mAlertDate > 0); } + /** + * 判断当前笔记是否为通话记录类型 + * @return true表示是通话记录(位于通话记录文件夹且包含电话号码) + */ public boolean isCallRecord() { + // 条件:父文件夹ID为通话记录文件夹ID,且电话号码不为空 return (mParentId == Notes.ID_CALL_RECORD_FOLDER && !TextUtils.isEmpty(mPhoneNumber)); } + /** + * 从Cursor中获取笔记类型 + * @param cursor 包含笔记数据的Cursor对象 + * @return 笔记类型的整数值(定义在Notes类中) + */ public static int getNoteType(Cursor cursor) { + // 通过预定义的列索引获取笔记类型字段值 return cursor.getInt(TYPE_COLUMN); } } diff --git a/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java b/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java index 51c9cb9..3194ff1 100644 --- a/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java +++ b/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java @@ -73,11 +73,16 @@ public class NotesListAdapter extends CursorAdapter { return mChoiceMode; } + /** + * 设置列表项的选择模式 + * @param mode true表示进入选择模式,false表示退出选择模式 + */ public void setChoiceMode(boolean mode) { + // 清空已选择的索引集合,重置选择状态 mSelectedIndex.clear(); + // 更新选择模式标志 mChoiceMode = mode; } - public void selectAll(boolean checked) { Cursor cursor = getCursor(); for (int i = 0; i < getCount(); i++) { diff --git a/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java b/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java index 38fbd65..3a4bbf8 100644 --- a/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java +++ b/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java @@ -425,15 +425,27 @@ public class NotesPreferenceActivity extends PreferenceActivity { } @Override +/** + * 选项菜单项目点击事件处理 + * 处理ActionBar/工具栏上的菜单项点击事件 + */ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + // 处理Home/返回按钮点击事件 case android.R.id.home: - // 点击返回按钮,返回到笔记列表Activity + // 创建返回笔记列表的Intent Intent intent = new Intent(this, NotesListActivity.class); + // 添加FLAG_ACTIVITY_CLEAR_TOP标志: + // 1. 如果目标Activity(NotesListActivity)已存在于栈中 + // 2. 则清除该Activity之上的所有Activity + // 3. 并将目标Activity移到栈顶(而不是创建新实例) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + // 启动笔记列表Activity startActivity(intent); return true; + default: + // 其他菜单项交给父类处理 return false; } } diff --git a/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java b/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java index ec6f819..9680956 100644 --- a/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java +++ b/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java @@ -46,14 +46,30 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { private static final String TAG = "NoteWidgetProvider"; @Override +/** + * 处理桌面小部件被删除的回调方法 + * 当用户从主屏幕移除笔记小部件时触发 + */ public void onDeleted(Context context, int[] appWidgetIds) { + // 创建内容值对象,用于存储要更新的字段和值 ContentValues values = new ContentValues(); + + // 将笔记的小部件ID设置为无效值 + // AppWidgetManager.INVALID_APPWIDGET_ID = -1 + // 表示该笔记不再关联任何桌面小部件 values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + + // 遍历所有被删除的小部件ID for (int i = 0; i < appWidgetIds.length; i++) { - context.getContentResolver().update(Notes.CONTENT_NOTE_URI, - values, - NoteColumns.WIDGET_ID + "=?", - new String[] { String.valueOf(appWidgetIds[i])}); + // 执行更新操作 + // 筛选条件:只更新WIDGET_ID等于当前被删除小部件ID的笔记 + // 参数数组:将小部件ID转换为字符串作为筛选条件参数 + context.getContentResolver().update( + Notes.CONTENT_NOTE_URI, // 笔记内容URI + values, // 要更新的字段和值 + NoteColumns.WIDGET_ID + "=?", // 筛选条件:小部件ID等于指定值 + new String[] { String.valueOf(appWidgetIds[i]) } // 筛选条件参数 + ); } } diff --git a/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java b/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java index adcb2f7..28b66e0 100644 --- a/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java +++ b/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java @@ -24,24 +24,49 @@ import net.micode.notes.data.Notes; import net.micode.notes.tool.ResourceParser; +/** + * 2x尺寸笔记桌面小部件提供者 + * 负责创建和更新2x尺寸的笔记小部件 + */ public class NoteWidgetProvider_2x extends NoteWidgetProvider { @Override + /** + * 处理小部件更新事件 + * 调用父类的更新方法完成小部件内容的刷新 + */ public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + // 委托给父类实现通用的小部件更新逻辑 super.update(context, appWidgetManager, appWidgetIds); } @Override + /** + * 获取小部件布局资源ID + * @return 2x尺寸小部件的布局资源ID + */ protected int getLayoutId() { + // 返回适合2x尺寸的小部件布局 return R.layout.widget_2x; } @Override + /** + * 获取背景资源ID + * @param bgId 背景颜色ID + * @return 对应的2x尺寸小部件背景资源ID + */ protected int getBgResourceId(int bgId) { + // 根据背景颜色ID获取对应的2x尺寸小部件背景资源 return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId); } @Override + /** + * 获取小部件类型 + * @return 小部件类型常量(2x尺寸) + */ protected int getWidgetType() { + // 返回表示2x尺寸小部件的类型常量 return Notes.TYPE_WIDGET_2X; } }