From ea51d7084088f719b36af5923e3d85a4277fd63b Mon Sep 17 00:00:00 2001
From: Yuyalu888 <946753883@qq.com>
Date: Wed, 18 Sep 2024 23:16:55 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AF=B9ui=E5=8C=85=E4=B8=8BNoteEditActivity.j?=
=?UTF-8?q?ava=E7=B1=BB=E5=92=8Cdata=E5=8C=85=E4=B8=8BNotes.java=E7=B1=BB?=
=?UTF-8?q?=E8=BF=9B=E8=A1=8C=E6=B3=A8=E9=87=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/net/micode/notes/data/Notes.java | 82 +++-
.../net/micode/notes/ui/NoteEditActivity.java | 452 +++++++++++++-----
2 files changed, 387 insertions(+), 147 deletions(-)
diff --git a/src/main/java/net/micode/notes/data/Notes.java b/src/main/java/net/micode/notes/data/Notes.java
index f240604..3c749e0 100644
--- a/src/main/java/net/micode/notes/data/Notes.java
+++ b/src/main/java/net/micode/notes/data/Notes.java
@@ -14,15 +14,24 @@
* limitations under the License.
*/
+/**
+ * 便签的数据库,该类主要实现了对便签的相关属性包括:
+ * Anthority, Tag,以及数据,联系人的信息进行管理,
+ * 实现了对若干属性的定义,并创建了DataColumns,DataColumns接口的定义,
+ * 该两个接口可用于其余类的实现,在便签管理中实现TextNote,CallNote两个类,
+ * 用于对便签内容的保存。
+ */
package net.micode.notes.data;
import android.net.Uri;
public class Notes {
- public static final String AUTHORITY = "micode_notes";
+ public static final String AUTHORITY = "micode_notes";// 定义应用的权限标识符
+ //设置标签,表示APP的名称是Notes
public static final String TAG = "Notes";
- public static final int TYPE_NOTE = 0;
- public static final int TYPE_FOLDER = 1;
- public static final int TYPE_SYSTEM = 2;
+ //定义不同类型的笔记或文件夹
+ public static final int TYPE_NOTE = 0;//笔记类型
+ public static final int TYPE_FOLDER = 1;//文件夹类型
+ public static final int TYPE_SYSTEM = 2;//系统类型
/**
* Following IDs are system folders' identifiers
@@ -30,11 +39,13 @@ public class Notes {
* {@link Notes#ID_TEMPARAY_FOLDER } is for notes belonging no folder
* {@link Notes#ID_CALL_RECORD_FOLDER} is to store call records
*/
- public static final int ID_ROOT_FOLDER = 0;
- public static final int ID_TEMPARAY_FOLDER = -1;
- public static final int ID_CALL_RECORD_FOLDER = -2;
- public static final int ID_TRASH_FOLER = -3;
+ //系统文件夹的ID定义
+ public static final int ID_ROOT_FOLDER = 0;//根目录ID默认
+ public static final int ID_TEMPARAY_FOLDER = -1;//临时文件夹ID
+ public static final int ID_CALL_RECORD_FOLDER = -2;//通话记录文件夹ID
+ public static final int ID_TRASH_FOLER = -3;//回收站文件夹ID
+ //Intent 额外数据键值
public static final String INTENT_EXTRA_ALERT_DATE = "net.micode.notes.alert_date";
public static final String INTENT_EXTRA_BACKGROUND_ID = "net.micode.notes.background_color_id";
public static final String INTENT_EXTRA_WIDGET_ID = "net.micode.notes.widget_id";
@@ -42,48 +53,58 @@ public class Notes {
public static final String INTENT_EXTRA_FOLDER_ID = "net.micode.notes.folder_id";
public static final String INTENT_EXTRA_CALL_DATE = "net.micode.notes.call_date";
- public static final int TYPE_WIDGET_INVALIDE = -1;
- public static final int TYPE_WIDGET_2X = 0;
- public static final int TYPE_WIDGET_4X = 1;
+ //小部件类型定义
+ public static final int TYPE_WIDGET_INVALIDE = -1;//无效小部件
+ public static final int TYPE_WIDGET_2X = 0;//2x 小部件
+ public static final int TYPE_WIDGET_4X = 1;// 4x 小部件
+ //数据常量类
public static class DataConstants {
+ //文本笔记的内容类型
public static final String NOTE = TextNote.CONTENT_ITEM_TYPE;
+ //通话笔记的内容类型
public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE;
}
/**
* Uri to query all notes and folders
*/
+ //查询所有笔记和文件夹的URI
public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note");
/**
* Uri to query data
*/
+ //查询数据的URI
public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data");
-
+ //笔记列定义接口
public interface NoteColumns {
/**
* The unique ID for a row
*
Type: INTEGER (long)
*/
+ //行的唯一ID
public static final String ID = "_id";
/**
* The parent's id for note or folder
* Type: INTEGER (long)
*/
+ //父项ID
public static final String PARENT_ID = "parent_id";
/**
* Created data for note or folder
* Type: INTEGER (long)
*/
+ //创建日期
public static final String CREATED_DATE = "created_date";
/**
* Latest modified date
* Type: INTEGER (long)
*/
+ //最新修改日期
public static final String MODIFIED_DATE = "modified_date";
@@ -91,30 +112,35 @@ public class Notes {
* Alert date
* Type: INTEGER (long)
*/
+ //提醒日期
public static final String ALERTED_DATE = "alert_date";
/**
* Folder's name or text content of note
* Type: TEXT
*/
+ //文件夹名称或笔记文本内容
public static final String SNIPPET = "snippet";
/**
* Note's widget id
* Type: INTEGER (long)
*/
+ //笔记的小部件ID
public static final String WIDGET_ID = "widget_id";
/**
* Note's widget type
* Type: INTEGER (long)
*/
+ //小部件类型
public static final String WIDGET_TYPE = "widget_type";
/**
* Note's background color's id
* Type: INTEGER (long)
*/
+ //笔记背景颜色ID
public static final String BG_COLOR_ID = "bg_color_id";
/**
@@ -122,86 +148,101 @@ public class Notes {
* note, it has at least one attachment
* Type: INTEGER
*/
+ //是否有附件
public static final String HAS_ATTACHMENT = "has_attachment";
/**
* Folder's count of notes
* Type: INTEGER (long)
*/
+ //笔记数量
public static final String NOTES_COUNT = "notes_count";
/**
* The file type: folder or note
* Type: INTEGER
*/
+ //文件类型
public static final String TYPE = "type";
/**
* The last sync id
* Type: INTEGER (long)
*/
+ //最后同步ID
public static final String SYNC_ID = "sync_id";
/**
* Sign to indicate local modified or not
* Type: INTEGER
*/
+ //标志是否本地已修改
public static final String LOCAL_MODIFIED = "local_modified";
/**
* Original parent id before moving into temporary folder
* Type : INTEGER
*/
+ //移动到临时文件夹前的原始父ID
public static final String ORIGIN_PARENT_ID = "origin_parent_id";
/**
* The gtask id
* Type : TEXT
*/
+ //Google任务ID
public static final String GTASK_ID = "gtask_id";
/**
* The version code
* Type : INTEGER (long)
*/
+ //版本号
public static final String VERSION = "version";
}
+ //数据列定义接口
public interface DataColumns {
/**
* The unique ID for a row
* Type: INTEGER (long)
*/
+ //行的唯一ID
public static final String ID = "_id";
/**
* The MIME type of the item represented by this row.
* Type: Text
*/
+ //该项的MIME类型
public static final String MIME_TYPE = "mime_type";
/**
* The reference id to note that this data belongs to
* Type: INTEGER (long)
*/
+ //该数据所属笔记的引用ID
public static final String NOTE_ID = "note_id";
/**
* Created data for note or folder
* Type: INTEGER (long)
*/
+ //创建日期
public static final String CREATED_DATE = "created_date";
/**
* Latest modified date
* Type: INTEGER (long)
*/
+ //最后修改日期
public static final String MODIFIED_DATE = "modified_date";
/**
* Data's content
* Type: TEXT
*/
+ //数据内容
public static final String CONTENT = "content";
@@ -210,6 +251,7 @@ public class Notes {
* integer data type
* Type: INTEGER
*/
+ //泛型数据列1(整数类型)
public static final String DATA1 = "data1";
/**
@@ -217,6 +259,7 @@ public class Notes {
* integer data type
* Type: INTEGER
*/
+ //泛型数据列2(整数类型)
public static final String DATA2 = "data2";
/**
@@ -224,6 +267,7 @@ public class Notes {
* TEXT data type
* Type: TEXT
*/
+ //泛型数据列3(文本类型)
public static final String DATA3 = "data3";
/**
@@ -231,6 +275,7 @@ public class Notes {
* TEXT data type
* Type: TEXT
*/
+ //泛型数据列4(文本类型)
public static final String DATA4 = "data4";
/**
@@ -238,42 +283,49 @@ public class Notes {
* TEXT data type
* Type: TEXT
*/
+ //泛型数据列5(文本类型)
public static final String DATA5 = "data5";
}
+ //文本笔记类,实现DataColumns接口
public static final class TextNote implements DataColumns {
/**
* Mode to indicate the text in check list mode or not
* Type: Integer 1:check list mode 0: normal mode
*/
+ //检查列表模式标识
public static final String MODE = DATA1;
public static final int MODE_CHECK_LIST = 1;
+ //内容类型
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note";
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note";
+ //内容URI
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note");
}
+ //通话笔记类,实现DataColumns接口
public static final class CallNote implements DataColumns {
/**
* Call date for this record
* Type: INTEGER (long)
*/
+ //通话日期
public static final String CALL_DATE = DATA1;
/**
* Phone number for this record
* Type: TEXT
*/
+ //电话号码
public static final String PHONE_NUMBER = DATA3;
-
+ //内容类型
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note";
-
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note";
-
+ //URI
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note");
}
}
diff --git a/src/main/java/net/micode/notes/ui/NoteEditActivity.java b/src/main/java/net/micode/notes/ui/NoteEditActivity.java
index 96a9ff8..716fc08 100644
--- a/src/main/java/net/micode/notes/ui/NoteEditActivity.java
+++ b/src/main/java/net/micode/notes/ui/NoteEditActivity.java
@@ -1,3 +1,6 @@
+/**
+ * 版权和许可证声明,指定了代码的许可协议为 Apache License 2.0。
+ */
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
@@ -16,6 +19,9 @@
package net.micode.notes.ui;
+/**
+ * 导入了 Android 开发所需的多个类库,包括 Activity、各种 UI 控件、数据处理工具等。
+ */
import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
@@ -51,7 +57,9 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
-
+/**
+ * 导入了项目内部的自定义类和接口,例如 R 资源文件、数据模型类、工具类等。
+ */
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.TextNote;
@@ -64,16 +72,25 @@ import net.micode.notes.ui.DateTimePickerDialog.OnDateTimeSetListener;
import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
import net.micode.notes.widget.NoteWidgetProvider_2x;
import net.micode.notes.widget.NoteWidgetProvider_4x;
-
+/**
+ * 导入了 Java 标准库中的集合类和正则表达式相关类。
+ */
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-
+/**
+ * 定义了一个名为 NoteEditActivity 的 Activity 类,
+ * 继承自 Activity 并实现了 OnClickListener、NoteSettingChangedListener
+ * 和 OnTextViewChangeListener 接口。
+ */
public class NoteEditActivity extends Activity implements OnClickListener,
NoteSettingChangedListener, OnTextViewChangeListener {
+ /**
+ * 定义了一个内部类 HeadViewHolder,用于保存头部视图的引用。
+ */
private class HeadViewHolder {
public TextView tvModified;
@@ -84,6 +101,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
public ImageView ibSetBgColor;
}
+ /**
+ * 定义了一个静态映射表 sBgSelectorBtnsMap,用于关联背景颜色按钮 ID 和相应的颜色值。
+ */
private static final Map sBgSelectorBtnsMap = new HashMap();
static {
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
@@ -93,6 +113,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sBgSelectorBtnsMap.put(R.id.iv_bg_white, ResourceParser.WHITE);
}
+ /**
+ * 定义了一个静态映射表 sBgSelectorSelectionMap,用于关联背景颜色值和相应的选择按钮 ID。
+ */
private static final Map sBgSelectorSelectionMap = new HashMap();
static {
sBgSelectorSelectionMap.put(ResourceParser.YELLOW, R.id.iv_bg_yellow_select);
@@ -102,6 +125,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select);
}
+ /**
+ * 定义了一个静态映射表 sFontSizeBtnsMap,用于关联字体大小按钮 ID 和相应的字体大小值。
+ */
private static final Map sFontSizeBtnsMap = new HashMap();
static {
sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE);
@@ -110,6 +136,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sFontSizeBtnsMap.put(R.id.ll_font_super, ResourceParser.TEXT_SUPER);
}
+ /**
+ * 定义了一个静态映射表 sFontSelectorSelectionMap,用于关联字体大小值和相应的选择按钮 ID。
+ */
private static final Map sFontSelectorSelectionMap = new HashMap();
static {
sFontSelectorSelectionMap.put(ResourceParser.TEXT_LARGE, R.id.iv_large_select);
@@ -118,34 +147,40 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SUPER, R.id.iv_super_select);
}
- private static final String TAG = "NoteEditActivity";
+ private static final String TAG = "NoteEditActivity";//定义了一个常量 TAG,用于日志记录。
- private HeadViewHolder mNoteHeaderHolder;
+ private HeadViewHolder mNoteHeaderHolder;//定义了一个 HeadViewHolder 对象 mNoteHeaderHolder,用于保存头部视图的引用。
- private View mHeadViewPanel;
+ private View mHeadViewPanel;//定义了一个 View 对象 mHeadViewPanel,用于保存头部视图面板的引用。
- private View mNoteBgColorSelector;
+ private View mNoteBgColorSelector;//定义了一个 View 对象 mNoteBgColorSelector,用于保存笔记背景颜色选择器的引用。
- private View mFontSizeSelector;
+ private View mFontSizeSelector;//定义了一个 View 对象 mFontSizeSelector,用于保存字体大小选择器的引用。
- private EditText mNoteEditor;
+ private EditText mNoteEditor;//定义了一个 EditText 对象 mNoteEditor,用于保存笔记编辑器的引用。
- private View mNoteEditorPanel;
+ private View mNoteEditorPanel;//定义了一个 View 对象 mNoteEditorPanel,用于保存笔记编辑面板的引用。
- private WorkingNote mWorkingNote;
+ private WorkingNote mWorkingNote;//定义了一个 WorkingNote 对象 mWorkingNote,用于保存当前正在编辑的笔记对象。
- private SharedPreferences mSharedPrefs;
- private int mFontSizeId;
+ private SharedPreferences mSharedPrefs;//定义了一个 SharedPreferences 对象 mSharedPrefs,用于保存应用偏好设置。
+ private int mFontSizeId;//定义了一个整型变量 mFontSizeId,用于保存字体大小 ID。
- private static final String PREFERENCE_FONT_SIZE = "pref_font_size";
+ private static final String PREFERENCE_FONT_SIZE = "pref_font_size";//定义了一个常量 PREFERENCE_FONT_SIZE,用于指定字体大小的偏好设置键。
- private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10;
+ private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10;//定义了一个常量 SHORTCUT_ICON_TITLE_MAX_LEN,用于指定快捷图标标题的最大长度。
+ /**
+ * 定义了两个常量 TAG_CHECKED 和 TAG_UNCHECKED,用于表示勾选和未勾选的状态标记。
+ */
public static final String TAG_CHECKED = String.valueOf('\u221A');
public static final String TAG_UNCHECKED = String.valueOf('\u25A1');
- private LinearLayout mEditTextList;
+ private LinearLayout mEditTextList;//定义了一个 LinearLayout 对象 mEditTextList,用于保存编辑文本列表的引用。
+ /**
+ * 定义了两个字符串变量 mUserQuery 和 Pattern 对象 mPattern,分别用于保存用户查询和正则表达式模式
+ */
private String mUserQuery;
private Pattern mPattern;
@@ -153,7 +188,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.note_edit);
-
+ /**
+ * 检查 savedInstanceState 是否为 null,如果是,则调用 initActivityState 方法初始化 Activity 状态。如果初始化失败,则结束 Activity。
+ * 如果初始化成功,则调用 initResources 方法初始化资源。
+ */
if (savedInstanceState == null && !initActivityState(getIntent())) {
finish();
return;
@@ -165,6 +203,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* Current activity may be killed when the memory is low. Once it is killed, for another time
* user load this activity, we should restore the former state
*/
+
+ /**
+ * 当用户内存不够时,当前活动会被杀掉,为了恢复之前的状态,重写了 onRestoreInstanceState 方法。
+ * 在 onRestoreInstanceState 方法中,从 savedInstanceState 中恢复 Activity 的状态。
+ * 如果 savedInstanceState 包含 Intent.EXTRA_UID,则创建一个新的 Intent 并设置 UID,然后调用 initActivityState 方法初始化 Activity 状态。
+ * 如果初始化失败,则结束 Activity,并记录日志。
+ * @param savedInstanceState
+ */
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
@@ -184,6 +230,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* If the user specified the {@link Intent#ACTION_VIEW} but not provided with id,
* then jump to the NotesListActivity
*/
+ /**
+ * initActivityState 方法用于初始化 Activity 的状态。
+ * 如果 Intent 的动作是 Intent.ACTION_VIEW,则获取笔记的 ID (noteId) 和用户查询 (mUserQuery)。
+ */
mWorkingNote = null;
if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) {
long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0);
@@ -192,11 +242,18 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* Starting from the searched result
*/
+ /**
+ * 如果 Intent 包含 SearchManager.EXTRA_DATA_KEY,则从搜索结果中获取笔记 ID 和用户查询。
+ */
if (intent.hasExtra(SearchManager.EXTRA_DATA_KEY)) {
noteId = Long.parseLong(intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY);
}
+ /**
+ * 检查笔记是否存在于数据库中,如果不存在,则跳转到 NotesListActivity 并显示错误提示,结束 Activity。
+ * 如果存在,则加载笔记并将其存储在 mWorkingNote 中。
+ */
if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) {
Intent jump = new Intent(this, NotesListActivity.class);
startActivity(jump);
@@ -211,9 +268,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return false;
}
}
+ //设置软键盘模式为隐藏且调整布局大小。
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
+ /**
+ * 如果 Intent 的动作是 Intent.ACTION_INSERT_OR_EDIT,则创建新的笔记。
+ * 获取文件夹 ID (folderId)、小部件 ID (widgetId)、小部件类型 (widgetType) 和背景资源 ID (bgResId)。
+ */
} else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) {
// New note
long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0);
@@ -225,6 +287,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
ResourceParser.getDefaultBgId(this));
// Parse call-record note
+ // 解析通话记录笔记
+ /**
+ * 如果 Intent 包含通话记录信息,则根据电话号码和通话日期查找笔记。
+ */
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
long callDate = intent.getLongExtra(Notes.INTENT_EXTRA_CALL_DATE, 0);
if (callDate != 0 && phoneNumber != null) {
@@ -232,6 +298,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Log.w(TAG, "The call record number is null");
}
long noteId = 0;
+ //如果找到笔记,则加载笔记;
if ((noteId = DataUtils.getNoteIdByPhoneNumberAndCallDate(getContentResolver(),
phoneNumber, callDate)) > 0) {
mWorkingNote = WorkingNote.load(this, noteId);
@@ -240,49 +307,67 @@ public class NoteEditActivity extends Activity implements OnClickListener,
finish();
return false;
}
+ //如果没有找到,则创建一个空笔记,并将其转换为通话记录笔记。
} else {
mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId,
widgetType, bgResId);
mWorkingNote.convertToCallNote(phoneNumber, callDate);
}
+ //如果没有通话记录信息,则直接创建一个空笔记。
} else {
mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId, widgetType,
bgResId);
}
-
+ /**
+ * 设置软键盘模式为调整布局大小且显示软键盘。
+ */
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+ //如果 Intent 动作不明确,则记录错误日志并结束 Activity。
} else {
Log.e(TAG, "Intent not specified action, should not support");
finish();
return false;
- }
+ }//设置 mWorkingNote 的设置状态改变监听器。
mWorkingNote.setOnSettingStatusChangedListener(this);
return true;
}
+ /**
+ * 在 onResume 方法中,调用父类的 onResume 方法,并初始化笔记界面。
+ */
@Override
protected void onResume() {
super.onResume();
initNoteScreen();
}
+ /**
+ * 初始化笔记界面。
+ */
private void initNoteScreen() {
mNoteEditor.setTextAppearance(this, TextAppearanceResources
- .getTexAppearanceResource(mFontSizeId));
+ .getTexAppearanceResource(mFontSizeId));//设置笔记编辑器的文本外观
+ /**
+ * 如果笔记是检查列表模式,则切换到列表模式;否则,设置笔记编辑器的内容并高亮显示用户查询结果。
+ */
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
switchToListMode(mWorkingNote.getContent());
} else {
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
mNoteEditor.setSelection(mNoteEditor.getText().length());
}
+ /**
+ * 遍历背景选择器映射表,隐藏所有背景选择器。
+ */
for (Integer id : sBgSelectorSelectionMap.keySet()) {
findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE);
}
+ //* 设置头部视图和笔记编辑面板的背景。
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
-
+ //设置头部视图中的修改时间。
mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(this,
mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
| DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
@@ -292,9 +377,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* TODO: Add the menu for setting alert. Currently disable it because the DateTimePicker
* is not ready
*/
+ //显示或隐藏警报头。
showAlertHeader();
}
+ /**
+ * 根据笔记是否有警报来显示或隐藏警报头。
+ */
private void showAlertHeader() {
if (mWorkingNote.hasClockAlert()) {
long time = System.currentTimeMillis();
@@ -312,6 +401,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
};
}
+ //在 onNewIntent 方法中,调用父类的 onNewIntent 方法,并初始化 Activity 状态。
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
@@ -326,30 +416,41 @@ 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
*/
+ /**
+ * 对于新笔记,如果没有笔记 ID,应该先保存它以生成一个 ID。
+ * 如果编辑的笔记不值得保存,则没有 ID,相当于创建新笔记。
+ */
+ //如果当前正在编辑的笔记还没有保存到数据库中,则先调用 saveNote 方法保存笔记。
if (!mWorkingNote.existInDatabase()) {
saveNote();
}
+ //将笔记的 ID 存入 outState 中,并记录日志。
outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId());
Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState");
}
@Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
+ public boolean dispatchTouchEvent(MotionEvent ev) {//在 dispatchTouchEvent 方法中,处理触摸事件。
+ /**
+ * 如果 mNoteBgColorSelector 或 mFontSizeSelector 可见,并且触摸位置不在它们的范围内,则隐藏这些选择器并返回 true。
+ */
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE
&& !inRangeOfView(mNoteBgColorSelector, ev)) {
mNoteBgColorSelector.setVisibility(View.GONE);
return true;
}
-
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) {
+ private boolean inRangeOfView(View view, MotionEvent ev) {//inRangeOfView 方法用于判断触摸事件的位置是否在指定视图的范围内。
+ //获取视图在屏幕上的位置,并计算其边界。
+ //如果触摸位置超出边界,则返回 false;否则返回 true。
int []location = new int[2];
view.getLocationOnScreen(location);
int x = location[0];
@@ -363,17 +464,21 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return true;
}
- private void initResources() {
+ private void initResources() {//initResources 方法用于初始化 Activity 中的各种视图组件。
+ /**
+ * 初始化标题面板、修改日期、警报图标、警报日期、背景颜色选择按钮、笔记编辑器、笔记编辑面板、背景颜色选择器、字体大小选择器等。
+ */
mHeadViewPanel = findViewById(R.id.note_title);
mNoteHeaderHolder = new HeadViewHolder();
mNoteHeaderHolder.tvModified = (TextView) findViewById(R.id.tv_modified_date);
mNoteHeaderHolder.ivAlertIcon = (ImageView) findViewById(R.id.iv_alert_icon);
mNoteHeaderHolder.tvAlertDate = (TextView) findViewById(R.id.tv_alert_date);
mNoteHeaderHolder.ibSetBgColor = (ImageView) findViewById(R.id.btn_set_bg_color);
- mNoteHeaderHolder.ibSetBgColor.setOnClickListener(this);
+ 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);
@@ -384,6 +489,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
View view = findViewById(id);
view.setOnClickListener(this);
};
+ //从共享偏好中读取字体大小,并进行边界检查
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
mFontSizeId = mSharedPrefs.getInt(PREFERENCE_FONT_SIZE, ResourceParser.BG_DEFAULT_FONT_SIZE);
/**
@@ -391,22 +497,31 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* The id may larger than the length of resources, in this case,
* return the {@link ResourceParser#BG_DEFAULT_FONT_SIZE}
*/
+ /**
+ * HACKME: 修复在共享偏好中存储资源 ID 的问题。
+ * ID 可能大于资源长度,在这种情况下,返回默认值。
+ */
+
if(mFontSizeId >= TextAppearanceResources.getResourcesSize()) {
mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE;
}
+ //初始化笔记编辑列表。
mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
}
@Override
protected void onPause() {
super.onPause();
- if(saveNote()) {
+ if(saveNote()) {//调用 saveNote 方法保存笔记,并记录日志。
Log.d(TAG, "Note data was saved with length:" + mWorkingNote.getContent().length());
}
- clearSettingState();
+ clearSettingState();//清除设置状态。
}
- private void updateWidget() {
+ private void updateWidget() {//updateWidget 方法用于更新小部件。
+ /**
+ * 根据笔记的小部件类型创建不同的Intent,并设置相应的类。
+ */
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) {
intent.setClass(this, NoteWidgetProvider_2x.class);
@@ -420,38 +535,47 @@ public class NoteEditActivity extends Activity implements OnClickListener,
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
mWorkingNote.getWidgetId()
});
-
+ //发送广播更新小部件,并设置结果
sendBroadcast(intent);
setResult(RESULT_OK, intent);
}
- public void onClick(View v) {
+ public void onClick(View v) {//onClick 方法用于处理各种按钮的点击事件。
+ /**
+ * 处理背景颜色选择按钮、字体大小选择按钮等。
+ * 更新笔记的背景颜色和字体大小,并保存到共享偏好中。
+ * 切换笔记的模式(检查列表模式或普通模式)。
+ */
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)) {
+ if (id == R.id.btn_set_bg_color) {//这部分代码处理背景颜色选择按钮的点击事件。如果用户点击了背景颜色选择按钮 (btn_set_bg_color),执行以下操作:
+ mNoteBgColorSelector.setVisibility(View.VISIBLE);//显示背景颜色选择器。
+ findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(View.VISIBLE);//显示当前笔记的背景颜色选中状态。
+ } else if (sBgSelectorBtnsMap.containsKey(id)) {//这部分代码处理不同背景颜色按钮的点击事件(背景颜色按钮的 ID 存在于 sBgSelectorBtnsMap 映射中)。如果用户选择了某个背景颜色,执行以下操作:
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);
- 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());
+ View.GONE);////隐藏之前选中的背景颜色。
+ mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));//更新当前笔记的背景颜色 ID 为用户选择的新颜色。
+ mNoteBgColorSelector.setVisibility(View.GONE);//隐藏背景颜色选择器。
+ } else if (sFontSizeBtnsMap.containsKey(id)) {//这部分代码处理字体大小选择按钮的点击事件。如果点击的按钮属于字体大小选择按钮,执行以下操作:
+ findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.GONE);//隐藏之前选择的字体大小状态。
+ mFontSizeId = sFontSizeBtnsMap.get(id);//更新字体大小 ID 为用户选择的新值。
+ 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));
+ TextAppearanceResources.getTexAppearanceResource(mFontSizeId));//根据选择的字体大小更新笔记编辑器的文本外观。
}
- mFontSizeSelector.setVisibility(View.GONE);
+ mFontSizeSelector.setVisibility(View.GONE);//隐藏字体大小选择器。
}
}
+ /**
+ * 在 onBackPressed 方法中,首先清除设置状态。
+ * 如果清除成功,则返回。
+ * 否则,保存笔记并调用父类的 onBackPressed 方法。
+ */
@Override
public void onBackPressed() {
if(clearSettingState()) {
@@ -462,6 +586,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
super.onBackPressed();
}
+ /**
+ * clearSettingState 方法用于清除设置状态。
+ * 如果背景颜色选择器或字体大小选择器可见,则隐藏它们并返回 true。
+ * 否则返回 false。
+ * @return
+ */
private boolean clearSettingState() {
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE) {
mNoteBgColorSelector.setVisibility(View.GONE);
@@ -473,6 +603,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return false;
}
+ /**
+ * onBackgroundColorChanged 方法用于处理背景颜色变化。
+ * 更新笔记编辑面板和标题面板的背景。
+ */
public void onBackgroundColorChanged() {
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.VISIBLE);
@@ -481,22 +615,34 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
@Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- if (isFinishing()) {
+ public boolean onPrepareOptionsMenu(Menu menu) {//对选择菜单的准备
+ if (isFinishing()) {//如果窗口正在关闭,则不做处理
return true;
}
- clearSettingState();
- menu.clear();
+ clearSettingState();//调用 clearSettingState 方法清除设置状态。
+ menu.clear();//清空当前菜单。
+ /**
+ * 如果笔记在通话记录文件夹中,则加载 call_note_edit 菜单。
+ * 否则,加载 note_edit 菜单。
+ */
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);
}
+ /**
+ * 如果笔记有闹钟提醒,则隐藏 menu_alert 菜单项。
+ * 否则,隐藏 menu_delete_remind 菜单项。
+ */
if (mWorkingNote.hasClockAlert()) {
menu.findItem(R.id.menu_alert).setVisible(false);
} else {
@@ -507,6 +653,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
@Override
public boolean onOptionsItemSelected(MenuItem item) {
+ //处理菜单项点击事件:
+ //根据不同的菜单项执行相应的操作。
switch (item.getItemId()) {
case R.id.menu_new_note:
createNewNote();
@@ -553,11 +701,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return true;
}
+ //显示日期时间选择对话框
private void setReminder() {
- DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis());
+ DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis());//创建一个新的 DateTimePickerDialog 实例。
d.setOnDateTimeSetListener(new OnDateTimeSetListener() {
public void OnDateTimeSet(AlertDialog dialog, long date) {
- mWorkingNote.setAlertDate(date , true);
+ mWorkingNote.setAlertDate(date , true);//将用户选择的时间戳 (date) 赋值给了 mWorkingNote 对象的 alertDate 属性,并且设置了一个标志为 true。
}
});
d.show();
@@ -567,14 +716,18 @@ 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) {
+ private void sendTo(Context context, String info) {//将笔记通过支持 Intent#ACTION_SEND 动作的应用分享出去。
+ //创建一个 Intent,设置动作 Intent.ACTION_SEND,并将笔记文本添加到 Intent 中,最后启动该 Intent
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, info);
intent.setType("text/plain");
context.startActivity(intent);
}
- private void createNewNote() {
+ private void createNewNote() {//创建一个新的笔记。
+ /**
+ * 保存当前编辑的笔记,然后启动一个新的 NoteEditActivity。
+ */
// Firstly, save current editing notes
saveNote();
@@ -586,50 +739,54 @@ public class NoteEditActivity extends Activity implements OnClickListener,
startActivity(intent);
}
- private void deleteCurrentNote() {
- if (mWorkingNote.existInDatabase()) {
- HashSet ids = new HashSet();
+ private void deleteCurrentNote() {//删除当前笔记。
+
+ if (mWorkingNote.existInDatabase()) { // 检查当前笔记是否存在于数据库中。
+ HashSet ids = new HashSet();//创建一个 HashSet 用来存储笔记 ID,这里使用 HashSet 避免重复。
long id = mWorkingNote.getNoteId();
if (id != Notes.ID_ROOT_FOLDER) {
- ids.add(id);
+ ids.add(id);// 如果笔记 ID 不是根文件夹 ID,则添加到集合中。
} else {
- Log.d(TAG, "Wrong note id, should not happen");
+ Log.d(TAG, "Wrong note id, should not happen"); // 如果是根文件夹 ID,则记录一条调试信息
}
- if (!isSyncMode()) {
- if (!DataUtils.batchDeleteNotes(getContentResolver(), ids)) {
+ if (!isSyncMode()) {//检查是否处于同步模式,如果不是,则直接删除笔记
+ if (!DataUtils.batchDeleteNotes(getContentResolver(), ids)) {//调用 DataUtils.batchDeleteNotes 方法批量删除笔记,如果删除失败,则记录错误信息。
Log.e(TAG, "Delete Note error");
}
- } else {
+ } 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);
+ mWorkingNote.markDeleted(true);//标记笔记为已删除,更新笔记的状态
}
- private boolean isSyncMode() {
- return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
+ private boolean isSyncMode() {//判断是否处于同步模式
+ return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;//检查是否有同步账户名称设置,如果有,则认为处于同步模式。
}
- public void onClockAlertChanged(long date, boolean set) {
+ public void onClockAlertChanged(long date, boolean set) {//处理闹钟提醒的设置或取消。
/**
* User could set clock to an unsaved note, so before setting the
* alert clock, we should save the note first
*/
- if (!mWorkingNote.existInDatabase()) {
+ /**
+ * 用户可能对未保存的笔记设置闹钟,所以在设置提醒之前应该先保存笔记。
+ */
+ if (!mWorkingNote.existInDatabase()) {// // 如果笔记不在数据库中,则先保存笔记
saveNote();
}
- if (mWorkingNote.getNoteId() > 0) {
- Intent intent = new Intent(this, AlarmReceiver.class);
- intent.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mWorkingNote.getNoteId()));
- PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
- AlarmManager alarmManager = ((AlarmManager) getSystemService(ALARM_SERVICE));
- showAlertHeader();
- if(!set) {
- alarmManager.cancel(pendingIntent);
- } else {
- alarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent);
+ if (mWorkingNote.getNoteId() > 0) {//检查笔记 ID 是否有效,如果有效,则继续设置或取消提醒。
+ Intent intent = new Intent(this, AlarmReceiver.class);//创建一个新的 Intent,指向 AlarmReceiver,用于接收闹钟提醒。
+ intent.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mWorkingNote.getNoteId()));//设置 Intent 数据为笔记的 URI,以便 AlarmReceiver 可以识别具体的笔记
+ PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); // 创建一个 PendingIntent 用于稍后触发广播接收器。
+ AlarmManager alarmManager = ((AlarmManager) getSystemService(ALARM_SERVICE)); // 获取系统服务 AlarmManager。
+ showAlertHeader();// 显示提醒头
+ if(!set) {// 如果是取消提醒。
+ alarmManager.cancel(pendingIntent);// 取消已设置的提醒。
+ } else {// 如果是设置提醒。
+ alarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent); // 设置提醒时间。
}
} else {
/**
@@ -637,64 +794,73 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* not worthy saving), we have no note id, remind the user that he
* should input something
*/
+ /**
+ * 存在一种情况,用户没有输入任何内容(笔记不值得保存),我们没有笔记 ID,提示用户应输入一些内容。
+ */
Log.e(TAG, "Clock alert setting error");
showToast(R.string.error_note_empty_for_clock);
}
}
- public void onWidgetChanged() {
+ public void onWidgetChanged() {//更新小部件
updateWidget();
}
- public void onEditTextDelete(int index, String text) {
- int childCount = mEditTextList.getChildCount();
- if (childCount == 1) {
+ public void onEditTextDelete(int index, String text) {//在清单模式下单删除一行时将后一行的文本移动到前一行。
+ int childCount = mEditTextList.getChildCount();//获取 mEditTextList 的子视图数量,即当前编辑区中的文本框数量。
+ Log.e(TAG, "onEditTextDelete: "+childCount);
+ if (childCount == 1) {//如果只有一个子视图,直接返回,不做任何操作
return;
}
- for (int i = index + 1; i < childCount; i++) {
+ for (int i = index + 1; i < childCount; i++) {//遍历从 index + 1 开始的所有子视图,更新它们的索引值
((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text))
- .setIndex(i - 1);
+ .setIndex(i - 1);//获取第 i 个子视图中的 NoteEditText 组件,并将其索引值减一,因为删除了一个视图,所以后续的索引都需要向前移动一位。
}
- mEditTextList.removeViewAt(index);
- NoteEditText edit = null;
- if(index == 0) {
+ mEditTextList.removeViewAt(index);//从 mEditTextList 中移除指定索引的视图
+ NoteEditText edit = null;//初始化一个 NoteEditText 对象 edit 为 null。
+ if(index == 0) {//如果删除的是第一行。
edit = (NoteEditText) mEditTextList.getChildAt(0).findViewById(
- R.id.et_edit_text);
+ R.id.et_edit_text);//获取第一个子视图中的 NoteEditText 组件。
} else {
edit = (NoteEditText) mEditTextList.getChildAt(index - 1).findViewById(
- R.id.et_edit_text);
+ R.id.et_edit_text);//获取删除位置前一个子视图中的 NoteEditText 组件。
}
- int length = edit.length();
- edit.append(text);
- edit.requestFocus();
- edit.setSelection(length);
+ Log.e(TAG, "onEditTextDelete: " +text);
+ int length = edit.length();//获取当前行的文本长度。
+ edit.append(text);//将删除的文本追加到当前行的末尾。
+ edit.requestFocus();//将焦点设置到当前视图上,方便用户继续编辑。
+ edit.setSelection(length);//设置光标位置到追加文本的末尾,确保光标在正确的位置。
}
- public void onEditTextEnter(int index, String text) {
+ public void onEditTextEnter(int index, String text) {//处理编辑文本回车操作。
/**
* 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.addView(view, index);
+ mEditTextList.addView(view, index);//通过 getListItem 方法创建一个新的列表项视图,并将其添加到 mEditTextList 的指定位置。
NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
edit.requestFocus();
- edit.setSelection(0);
- for (int i = index + 1; i < mEditTextList.getChildCount(); i++) {
+ edit.setSelection(0);//将焦点设置到新添加的 NoteEditText 组件上,并将光标位置设置为文本开头。
+ for (int i = index + 1; i < mEditTextList.getChildCount(); i++) {//遍历从 index + 1 开始的所有子视图,并更新它们的索引值。
((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text))
.setIndex(i);
}
}
- private void switchToListMode(String text) {
- mEditTextList.removeAllViews();
- String[] items = text.split("\n");
+ private void switchToListMode(String text) {//将编辑模式切换到清单模式。
+ mEditTextList.removeAllViews();//移除 mEditTextList 中的所有子视图。
+ String[] items = text.split("\n");//将输入的文本按换行符分割成多个项目。
int index = 0;
+ /**
+ * 遍历每个项目,创建相应的列表项视图并添加到 mEditTextList 中。
+ */
for (String item : items) {
if(!TextUtils.isEmpty(item)) {
mEditTextList.addView(getListItem(item, index));
@@ -702,19 +868,19 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
}
mEditTextList.addView(getListItem("", index));
- mEditTextList.getChildAt(index).findViewById(R.id.et_edit_text).requestFocus();
+ mEditTextList.getChildAt(index).findViewById(R.id.et_edit_text).requestFocus();//将焦点设置到最后一个列表项的 NoteEditText 组件上。
mNoteEditor.setVisibility(View.GONE);
- mEditTextList.setVisibility(View.VISIBLE);
+ mEditTextList.setVisibility(View.VISIBLE);//隐藏 mNoteEditor 并显示 mEditTextList。
}
- private Spannable getHighlightQueryResult(String fullText, String userQuery) {
- SpannableString spannable = new SpannableString(fullText == null ? "" : fullText);
- if (!TextUtils.isEmpty(userQuery)) {
+ private Spannable getHighlightQueryResult(String fullText, String userQuery) {//高亮显示查询结果。
+ SpannableString spannable = new SpannableString(fullText == null ? "" : fullText);//将输入的文本转换为 SpannableString。
+ if (!TextUtils.isEmpty(userQuery)) {//根据 userQuery 编译一个正则表达式。
mPattern = Pattern.compile(userQuery);
Matcher m = mPattern.matcher(fullText);
int start = 0;
- while (m.find(start)) {
+ while (m.find(start)) {//遍历所有匹配项,并为每个匹配项设置背景色高亮。
spannable.setSpan(
new BackgroundColorSpan(this.getResources().getColor(
R.color.user_query_highlight)), m.start(), m.end(),
@@ -725,12 +891,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return spannable;
}
- private View getListItem(String item, int index) {
+ private View getListItem(String item, int index) {//获取列表项视图。
View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null);
final NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
- edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
+ edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));//设置 NoteEditText 的文本样式。
CheckBox cb = ((CheckBox) view.findViewById(R.id.cb_edit_item));
- cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {//当复选框状态改变时,更新 NoteEditText 的样式即文字是否有删除线。
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
@@ -739,7 +905,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
}
});
-
+ /**
+ * //根据输入文本的前缀设置复选框的状态
+ */
if (item.startsWith(TAG_CHECKED)) {
cb.setChecked(true);
edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
@@ -752,26 +920,27 @@ public class NoteEditActivity extends Activity implements OnClickListener,
edit.setOnTextViewChangeListener(this);
edit.setIndex(index);
- edit.setText(getHighlightQueryResult(item, mUserQuery));
+ edit.setText(getHighlightQueryResult(item, mUserQuery));//设置 NoteEditText 的文本,并进行高亮处理
return view;
}
- public void onTextChange(int index, boolean hasText) {
+ public void onTextChange(int index, boolean hasText) {//处理文本变化事件
+ //:确保 index 不超出 mEditTextList 的子视图数量。
if (index >= mEditTextList.getChildCount()) {
Log.e(TAG, "Wrong index, should not happen");
return;
}
- if(hasText) {
+ if(hasText) {//根据是否有文本内容设置复选框的可见性。
mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.VISIBLE);
} else {
mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.GONE);
}
}
- public void onCheckListModeChanged(int oldMode, int newMode) {
+ public void onCheckListModeChanged(int oldMode, int newMode) {//处理检查列表模式变化。
if (newMode == TextNote.MODE_CHECK_LIST) {
- switchToListMode(mNoteEditor.getText().toString());
- } else {
+ switchToListMode(mNoteEditor.getText().toString());//如果模式为 MODE_CHECK_LIST,则调用 switchToListMode 方法切换到列表模式。
+ } else {//否则,设置 mNoteEditor 的文本,并切换视图的可见性。
if (!getWorkingText()) {
mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ",
""));
@@ -782,9 +951,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
}
- private boolean getWorkingText() {
+ private boolean getWorkingText() {//获取当前编辑的文本
boolean hasChecked = false;
- if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
+ if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {//如果当前模式为 TextNote.MODE_CHECK_LIST,则遍历 mEditTextList 中的所有子视图。
+ /**
+ * 根据每个 NoteEditText 的内容和复选框的状态构建最终的文本,并存储到 StringBuilder 中。
+ */
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mEditTextList.getChildCount(); i++) {
View view = mEditTextList.getChildAt(i);
@@ -798,16 +970,16 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
}
}
- mWorkingNote.setWorkingText(sb.toString());
+ mWorkingNote.setWorkingText(sb.toString());//将构建好的文本设置到 mWorkingNote 中。
} else {
mWorkingNote.setWorkingText(mNoteEditor.getText().toString());
}
return hasChecked;
}
- private boolean saveNote() {
- getWorkingText();
- boolean saved = mWorkingNote.saveNote();
+ private boolean saveNote() {//保存当前编辑的笔记。
+ getWorkingText();//调用 getWorkingText 方法获取当前编辑的文本。
+ boolean saved = mWorkingNote.saveNote();//调用 mWorkingNote.saveNote() 方法保存笔记。
if (saved) {
/**
* There are two modes from List view to edit view, open one note,
@@ -816,26 +988,38 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* new node requires to the top of the list. This code
* {@link #RESULT_OK} is used to identify the create/edit state
*/
- setResult(RESULT_OK);
+ /**
+ * 从列表视图进入编辑视图有两种模式:打开一个笔记或创建/编辑一个节点。
+ * 打开一个节点后,返回列表视图时需要回到原来的位置;
+ * 而创建一个新的节点后,返回列表视图时需要回到列表的顶部。
+ * 这里的代码 {@link #RESULT_OK} 用于区分创建和编辑的状态。
+ */
+ setResult(RESULT_OK);//如果保存成功,设置结果为 RESULT_OK。
}
return saved;
}
- private void sendToDesktop() {
+ private void sendToDesktop() {//将笔记发送到桌面作为快捷方式。
/**
* Before send message to home, we should make sure that current
* editing note is exists in databases. So, for new note, firstly
* save it
*/
- if (!mWorkingNote.existInDatabase()) {
+ if (!mWorkingNote.existInDatabase()) {//如果当前笔记不在数据库中,先保存笔记
saveNote();
}
- if (mWorkingNote.getNoteId() > 0) {
+ if (mWorkingNote.getNoteId() > 0) {//如果笔记存在且有 noteId,创建一个 Intent 用于发送到桌面。
Intent sender = new Intent();
Intent shortcutIntent = new Intent(this, NoteEditActivity.class);
+ /**
+ * 设置 Intent 的参数,包括快捷方式的意图、名称和图标资源。
+ */
shortcutIntent.setAction(Intent.ACTION_VIEW);
shortcutIntent.putExtra(Intent.EXTRA_UID, mWorkingNote.getNoteId());
+ /**
+ * 发送广播安装快捷方式,并显示提示信息
+ */
sender.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
sender.putExtra(Intent.EXTRA_SHORTCUT_NAME,
makeShortcutIconTitle(mWorkingNote.getContent()));
@@ -845,7 +1029,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sender.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
showToast(R.string.info_note_enter_desktop);
sendBroadcast(sender);
- } else {
+ } else {//如果没有 noteId,记录错误日志并显示提示信息。
/**
* There is the condition that user has input nothing (the note is
* not worthy saving), we have no note id, remind the user that he
@@ -856,18 +1040,22 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
}
- private String makeShortcutIconTitle(String content) {
+ private String makeShortcutIconTitle(String content) {//生成快捷方式图标标题。
+ /**
+ * 去除 content 中的 TAG_CHECKED 和 TAG_UNCHECKED
+ */
content = content.replace(TAG_CHECKED, "");
content = content.replace(TAG_UNCHECKED, "");
+ //如果内容长度超过最大长度 SHORTCUT_ICON_TITLE_MAX_LEN,截取前部分,否则返回原内容。
return content.length() > SHORTCUT_ICON_TITLE_MAX_LEN ? content.substring(0,
SHORTCUT_ICON_TITLE_MAX_LEN) : content;
}
- private void showToast(int resId) {
+ private void showToast(int resId) {//显示一个 Toast 消息。
showToast(resId, Toast.LENGTH_SHORT);
}
- private void showToast(int resId, int duration) {
+ private void showToast(int resId, int duration) {//显示一个带有指定持续时间的 Toast 消息。
Toast.makeText(this, resId, duration).show();
}
}