diff --git a/doc/report.docx b/doc/report.docx index dedc5fa..63f6a49 100644 Binary files a/doc/report.docx and b/doc/report.docx differ diff --git a/src/main/java/net/micode/notes/ui/NoteEditActivity.java b/src/main/java/net/micode/notes/ui/NoteEditActivity.java index 7b3ba28..462f91f 100644 --- a/src/main/java/net/micode/notes/ui/NoteEditActivity.java +++ b/src/main/java/net/micode/notes/ui/NoteEditActivity.java @@ -71,9 +71,16 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; - +/** + * @classname: NoteEditActivity + * @description:NoteEditActivity 继承于 Activity 实现了OnClickListener,NoteSettingChangedListener, OnTextViewChangeListener三个接口 + * 这个类主要完成对菜单功能的定义,显示与实现,是与用户交互的组件的主体 + * @date: 2023/12/27 0:08 + * @author: Xia Yanbo +*/ public class NoteEditActivity extends Activity implements OnClickListener, NoteSettingChangedListener, OnTextViewChangeListener { + //定义视图组件的基本数据(后面出现在了操作菜可选项里) private class HeadViewHolder { public TextView tvModified; @@ -83,7 +90,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, public ImageView ibSetBgColor; } - + //颜色可选项的视图——色板的显示 private static final Map sBgSelectorBtnsMap = new HashMap(); static { sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW); @@ -101,7 +108,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, sBgSelectorSelectionMap.put(ResourceParser.GREEN, R.id.iv_bg_green_select); sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select); } - + //字体大小的视图 private static final Map sFontSizeBtnsMap = new HashMap(); static { sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE); @@ -118,37 +125,48 @@ 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"; // 用于日志打印的标签,分类接收消息 + + private HeadViewHolder mNoteHeaderHolder; // 列表头视图容器持有者 + + private View mHeadViewPanel; // 头部视图面板 - private HeadViewHolder mNoteHeaderHolder; + private View mNoteBgColorSelector; // 笔记背景颜色选择器视图 - private View mHeadViewPanel; + private View mFontSizeSelector; // 字体大小选择器视图 - private View mNoteBgColorSelector; + private EditText mNoteEditor; // 笔记编辑器输入框 - private View mFontSizeSelector; + private View mNoteEditorPanel; // 笔记编辑器面板 - private EditText mNoteEditor; + private WorkingNote mWorkingNote; // 当前正在编辑的工作笔记对象 - private View mNoteEditorPanel; + private SharedPreferences mSharedPrefs; // 用于存储和检索应用偏好设置的对象 - private WorkingNote mWorkingNote; + private int mFontSizeId; // 当前选中的字体大小的资源ID - private SharedPreferences mSharedPrefs; - private int mFontSizeId; + private static final String PREFERENCE_FONT_SIZE = "pref_font_size"; // 偏好设置中用于保存字体大小的键 - private static final String PREFERENCE_FONT_SIZE = "pref_font_size"; + private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10; // 快捷方式图标标题的最大长度 - private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10; + public static final String TAG_CHECKED = String.valueOf('\u221A'); // 特殊符号,对钩(可能用于任务视图中表示任务已完成) - public static final String TAG_CHECKED = String.valueOf('\u221A'); - public static final String TAG_UNCHECKED = String.valueOf('\u25A1'); + public static final String TAG_UNCHECKED = String.valueOf('\u25A1'); // 特殊符号,空心方块(可能用于任务视图中表示任务未完成) - private LinearLayout mEditTextList; + private LinearLayout mEditTextList; // 线性布局,可能用于动态添加或显示多个EditText - private String mUserQuery; - private Pattern mPattern; + private String mUserQuery; // 用户输入的查询字符串 + private Pattern mPattern; // 用于匹配用户查询的正则表达式模式对象 + + /** + * @classname: NoteEditActivity + * @methodname onCreate + * @description:在活动创建之前进行初始化工作:包括视图的准备,资源的加载 + * @date: 2023/12/25 8:34 + * @author: Xia Yanbo + * @param:保存的设置的状态 + */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -164,58 +182,71 @@ 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 + * 当重新使用某个活动时,把它恢复到之前离开的状态 */ @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - if (savedInstanceState != null && savedInstanceState.containsKey(Intent.EXTRA_UID)) { + super.onRestoreInstanceState(savedInstanceState);//调用父类 + if (savedInstanceState != null && savedInstanceState.containsKey(Intent.EXTRA_UID)) {//检查保存的状态是否为空,是否包含特定意图 Intent intent = new Intent(Intent.ACTION_VIEW); - intent.putExtra(Intent.EXTRA_UID, savedInstanceState.getLong(Intent.EXTRA_UID)); - if (!initActivityState(intent)) { - finish(); - return; + intent.putExtra(Intent.EXTRA_UID, savedInstanceState.getLong(Intent.EXTRA_UID));//之前保存的意图附加其上 + if (!initActivityState(intent)) { // 调用 initActivityState 方法来处理这个 Intent,可能进行一些初始化工作或状态设置。 + finish(); // 如果 initActivityState 方法返回 false,表示初始化失败,此时结束当前活动。 + return; // 结束当前方法。 } Log.d(TAG, "Restoring from killed activity"); } } - + /** + * @classname: NoteEditActivity + * @methodname initActivityState + * @description: + * @date: 2023/12/25 8:44 + * @author: Xia Yanbo + * @param:intent意图消息 + * @return: + */ private boolean initActivityState(Intent intent) { /** * If the user specified the {@link Intent#ACTION_VIEW} but not provided with id, * then jump to the NotesListActivity */ mWorkingNote = null; - if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) { + if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) {//检查意图是否是查看 long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0); mUserQuery = ""; /** * Starting from the searched result + * 如果intent包含额外的数据键 */ if (intent.hasExtra(SearchManager.EXTRA_DATA_KEY)) { + //解析数据键,获取笔记ID以及查询字符串 noteId = Long.parseLong(intent.getStringExtra(SearchManager.EXTRA_DATA_KEY)); mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY); } - + //如果笔记id在数据库中不可见 if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) { Intent jump = new Intent(this, NotesListActivity.class); - startActivity(jump); + startActivity(jump);//跳转到笔记集活动中 showToast(R.string.error_note_not_exist); finish(); return false; } else { - mWorkingNote = WorkingNote.load(this, noteId); - if (mWorkingNote == null) { + mWorkingNote = WorkingNote.load(this, noteId);//加载笔记对象 + if (mWorkingNote == null) {//如果笔记对象为空,记录错误日志并且结束当前活动 Log.e(TAG, "load note failed with note id" + noteId); finish(); return false; } } + // 设置软键盘状态为隐藏,调整窗口大小以适应内容 getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); - } else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) { + } else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) {//否则,意图并非查看的情况 // New note + //获取额外的数据各类ID以及类型等数据 long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0); int widgetId = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); @@ -227,7 +258,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, // Parse call-record note String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); long callDate = intent.getLongExtra(Notes.INTENT_EXTRA_CALL_DATE, 0); - if (callDate != 0 && phoneNumber != null) { + if (callDate != 0 && phoneNumber != null) {//负责消息通知 if (TextUtils.isEmpty(phoneNumber)) { Log.w(TAG, "The call record number is null"); } @@ -247,7 +278,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, } } else { mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId, widgetType, - bgResId); + bgResId);//电话号码和提醒日期都为空,直接创建新表 } getWindow().setSoftInputMode( @@ -263,26 +294,33 @@ public class NoteEditActivity extends Activity implements OnClickListener, } @Override + //初始化屏幕 protected void onResume() { super.onResume(); initNoteScreen(); } - + // 定义一个私有方法initNoteScreen,用于初始化Note屏幕 private void initNoteScreen() { + // 设置Note编辑器的文本外观,使用指定的字体大小ID(标记,分别更改字体大小的功能可以类似实现) mNoteEditor.setTextAppearance(this, TextAppearanceResources .getTexAppearanceResource(mFontSizeId)); + // 检查当前Note是否处于Check List模式 if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { + // 如果处于Check List模式,调用switchToListMode方法并传入Note的内容 switchToListMode(mWorkingNote.getContent()); } else { + // 如果不是Check List模式,设置Note编辑器的文本为高亮查询结果,并选择文本的末尾 mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery)); mNoteEditor.setSelection(mNoteEditor.getText().length()); } + // 遍历sBgSelectorSelectionMap的键集合,并隐藏对应的视图。 for (Integer id : sBgSelectorSelectionMap.keySet()) { findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE); } + //给资源设置id 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 @@ -294,11 +332,17 @@ public class NoteEditActivity extends Activity implements OnClickListener, */ showAlertHeader(); } - + /** + * @classname: NoteEditActivity + * @methodname showAlertHeader + * @description:对于便签里设定的提醒时间,设置显示并在到达时间时发出提醒 + * @date: 2023/12/25 14:45 + * @author: Xia Yanbo + */ private void showAlertHeader() { if (mWorkingNote.hasClockAlert()) { long time = System.currentTimeMillis(); - if (time > mWorkingNote.getAlertDate()) { + if (time > mWorkingNote.getAlertDate()) {//判断时间是否到达 mNoteHeaderHolder.tvAlertDate.setText(R.string.note_alert_expired); } else { mNoteHeaderHolder.tvAlertDate.setText(DateUtils.getRelativeTimeSpanString( @@ -311,12 +355,19 @@ public class NoteEditActivity extends Activity implements OnClickListener, mNoteHeaderHolder.ivAlertIcon.setVisibility(View.GONE); }; } - + //根据新的意图重新初始化活动状态 @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); initActivityState(intent); } + /** + * @classname: NoteEditActivity + * @methodname onSaveInstanceState + * @description: 未保存到数据库的便签分配ID并保存 + * @date: 2023/12/25 14:59 + * @author: Xia Yanbo + */ @Override protected void onSaveInstanceState(Bundle outState) { @@ -332,7 +383,15 @@ public class NoteEditActivity extends Activity implements OnClickListener, outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId()); Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState"); } - + /** + * @classname: NoteEditActivity + * @methodname dispatchTouchEvent + * @description:当触摸事件不在范围内时,选择性隐藏显示的字体和主题颜色窗口选项 + * @date: 2023/12/25 15:10 + * @author: Xia Yanbo + * @param:ev 触摸事件 + * @return:boolean 是否进行隐藏 + */ @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (mNoteBgColorSelector.getVisibility() == View.VISIBLE @@ -348,21 +407,36 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return super.dispatchTouchEvent(ev); } - + /** + * @classname: NoteEditActivity + * @methodname inRangeOfView + * @description:检查触摸时间是否在视图的范围之内 + * @date: 2023/12/25 15:05 + * @author: Xia Yanbo + * @param:view 窗口视图 + * @param:ev 触摸事件 + * @return:boolean在范围内返回true,否则返回false + */ private boolean inRangeOfView(View view, MotionEvent ev) { int []location = new int[2]; - view.getLocationOnScreen(location); + view.getLocationOnScreen(location);//获取视图在屏幕上的位置 int x = location[0]; int y = location[1]; - if (ev.getX() < x + if (ev.getX() < x//判断事件有没有在视图所在的范围之内 || ev.getX() > (x + view.getWidth()) || ev.getY() < y || ev.getY() > (y + view.getHeight())) { - return false; - } + return false; + } return true; } - + /** + * @classname: NoteEditActivity + * @methodname initResources + * @description:初始化资源项,进行便签显示组件的准备与id初始化 + * @date: 2023/12/25 15:13 + * @author: Xia Yanbo + */ private void initResources() { mHeadViewPanel = findViewById(R.id.note_title); mNoteHeaderHolder = new HeadViewHolder(); @@ -390,13 +464,14 @@ public class NoteEditActivity extends Activity implements OnClickListener, * HACKME: Fix bug of store the resource id in shared preference. * The id may larger than the length of resources, in this case, * return the {@link ResourceParser#BG_DEFAULT_FONT_SIZE} + * 资源id大小可能会越界,这时返回缺省的BG_DEFAULT_FONT_SIZE */ if(mFontSizeId >= TextAppearanceResources.getResourcesSize()) { mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE; } mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list); } - + //一系列输入暂停时,进行便签内容的保存,并输出保存的长度信息 @Override protected void onPause() { super.onPause(); @@ -405,53 +480,66 @@ public class NoteEditActivity extends Activity implements OnClickListener, } clearSettingState(); } - + /** + * @classname: NoteEditActivity + * @methodname updateWidget + * @description:更新控件 + * @date: 2023/12/25 15:17 + * @author: Xia Yanbo + */ private void updateWidget() { Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); - if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) { + if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) {//检查当前工作笔记的控件类型,给对应的提供类 intent.setClass(this, NoteWidgetProvider_2x.class); } else if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_4X) { intent.setClass(this, NoteWidgetProvider_4x.class); - } else { + } else {//控件类型不受支持,打印错误日志 Log.e(TAG, "Unspported widget type"); return; } intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { - mWorkingNote.getWidgetId() + mWorkingNote.getWidgetId()//给意图intent添加要更新的控件的id }); - sendBroadcast(intent); - setResult(RESULT_OK, intent); + sendBroadcast(intent);//通知系统更新小控件 + setResult(RESULT_OK, intent);//通知调用者已完成 } - + /** + * @classname: NoteEditActivity + * @methodname onClick + * @description:通过点击的位置获取工作视图,并进行设置背景色,选择背景色,选择字体大小三种点击事件的处理 + * @date: 2023/12/25 15:30 + * @author: Xia Yanbo + * @param: v视图 + */ public void onClick(View v) { int id = v.getId(); - if (id == R.id.btn_set_bg_color) { + 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)) { + View.VISIBLE);//之前这里报错,已修改,显示背景色选择器 + } else if (sBgSelectorBtnsMap.containsKey(id)) { // 如果点击的是背景色选择器的某个按钮 findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( View.GONE); - mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id)); + mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));// 设置工作笔记的背景色ID为选择的背景色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) { + } else if (sFontSizeBtnsMap.containsKey(id)) {// 如果点击的是字体大小选择器的某个按钮 + findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.GONE);// 隐藏当前字体大小选择器 + mFontSizeId = sFontSizeBtnsMap.get(id); // 设置字体大小ID为选择的字体大小ID + mSharedPrefs.edit().putInt(PREFERENCE_FONT_SIZE, mFontSizeId).commit(); // 将字体大小ID保存到SharedPreferences中 + findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);// 显示新的字体大小选择器 + if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { // 如果笔记处于检查列表模式,则获取文本并切换到列表模式(两种模式是分开的) getWorkingText(); switchToListMode(mWorkingNote.getContent()); - } else { + } else { // 否则,设置文本的外观为新的字体大小 mNoteEditor.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId)); } mFontSizeSelector.setVisibility(View.GONE); } } - + //用户按下返回键时,清楚可见的设置状态并保存便签 @Override public void onBackPressed() { if(clearSettingState()) { @@ -461,7 +549,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, saveNote(); super.onBackPressed(); } - + //将还未被隐藏的选择器组件隐藏起来 private boolean clearSettingState() { if (mNoteBgColorSelector.getVisibility() == View.VISIBLE) { mNoteBgColorSelector.setVisibility(View.GONE); @@ -472,31 +560,45 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return false; } - + //当背景颜色发生更改时,更新相应的ui资源id public void onBackgroundColorChanged() { findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( View.VISIBLE); mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId()); mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId()); } - + /** + * @classname: NoteEditActivity + * @methodname onPrepareOptionsMenu + * @description:准备菜单项 + * @date: 2023/12/25 15:54 + * @author: Xia Yanbo + * @param:menu 当前Activity的菜单对象。 + * @return:如果已成功准备菜单,则返回true;否则返回false + */ @Override public boolean onPrepareOptionsMenu(Menu menu) { + // 如果Activity即将被销毁,则直接返回true,不再继续准备菜单 if (isFinishing()) { return true; } + //将还未隐藏的选择器组件隐藏 clearSettingState(); + //清除已有的菜单的所有项 menu.clear(); + // 根据笔记所在的文件夹ID来决定使用哪个菜单布局 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 { @@ -504,23 +606,32 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return true; } - + /** + * @classname: NoteEditActivity + * @methodname onOptionsItemSelected + * @description:根据所选择的菜单项执行相应的功能 + * @date: 2023/12/25 16:22 + * @author: Xia Yanbo + * @param:item 当前便签内的菜单 + * @return:boolean 已经选中事件被成功处理返回true,否则返回false + */ @Override public boolean onOptionsItemSelected(MenuItem item) { - + //新建笔记 if ( item.getItemId()==R.id.menu_new_note) { createNewNote(); } + //删除笔记 else if(item.getItemId()== 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); - builder.setMessage(getString(R.string.alert_message_delete_note)); - builder.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { + //弹出确认删除的警示框 + AlertDialog.Builder builder = new AlertDialog.Builder(this); // 创建一个AlertDialog的构建器 + builder.setTitle(getString(R.string.alert_title_delete)); // 设置标题为“删除” + builder.setIcon(android.R.drawable.ic_dialog_alert); // 设置图标为警告图标 + builder.setMessage(getString(R.string.alert_message_delete_note)); // 设置消息为删除笔记的提示信息 + builder.setPositiveButton(android.R.string.ok, // 设置确认按钮 + new DialogInterface.OnClickListener() {//点击事件监听器 public void onClick(DialogInterface dialog, int which) { deleteCurrentNote(); finish(); @@ -529,41 +640,47 @@ public class NoteEditActivity extends Activity implements OnClickListener, builder.setNegativeButton(android.R.string.cancel, null); builder.show(); } + //字体大小功能项 else if(item.getItemId()== R.id.menu_font_size) { - mFontSizeSelector.setVisibility(View.VISIBLE); + mFontSizeSelector.setVisibility(View.VISIBLE);//显示字体大小选择器 findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE); } + //列表模式 else if(item.getItemId()== R.id.menu_list_mode) { mWorkingNote.setCheckListMode(mWorkingNote.getCheckListMode() == 0 ? TextNote.MODE_CHECK_LIST : 0); } + //分享 else if(item.getItemId()== R.id.menu_share) { - getWorkingText(); - sendTo(this, mWorkingNote.getContent()); + getWorkingText();//获取当前笔记的文本内容 + sendTo(this, mWorkingNote.getContent());//分享出去 } + //发送到桌面 else if(item.getItemId()== R.id.menu_send_to_desktop) { sendToDesktop(); } + //设置提醒 else if(item.getItemId()== R.id.menu_alert) { setReminder(); } + //删除提醒 else if(item.getItemId()== R.id.menu_delete_remind) { mWorkingNote.setAlertDate(0, false); } return true; } - + //设置时间提醒 private void setReminder() { DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis()); - d.setOnDateTimeSetListener(new OnDateTimeSetListener() { + d.setOnDateTimeSetListener(new OnDateTimeSetListener() {//监听设置的时间 public void OnDateTimeSet(AlertDialog dialog, long date) { - mWorkingNote.setAlertDate(date , true); + mWorkingNote.setAlertDate(date , true);//设置提醒的日期时间 } }); d.show(); @@ -572,69 +689,87 @@ public class NoteEditActivity extends Activity implements OnClickListener, /** * Share note to apps that support {@link Intent#ACTION_SEND} action * and {@text/plain} type + * 将便签发送到支持的app应用 */ 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); + Intent intent = new Intent(Intent.ACTION_SEND);//意图为发送 + intent.putExtra(Intent.EXTRA_TEXT, info);//附加要发送的信息到intent + intent.setType("text/plain");//设定传输的类型 + context.startActivity(intent);//根据意图开始发送信息 } - + //创建一个新的便签 private void createNewNote() { // Firstly, save current editing notes - saveNote(); + saveNote();//保存当前便签 // For safety, start a new NoteEditActivity - finish(); + finish();//销毁资源,关闭当前便签 Intent intent = new Intent(this, NoteEditActivity.class); - intent.setAction(Intent.ACTION_INSERT_OR_EDIT); - intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mWorkingNote.getFolderId()); + intent.setAction(Intent.ACTION_INSERT_OR_EDIT);//设置活动为编辑 + intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mWorkingNote.getFolderId());//附加包和便签的id startActivity(intent); } - + /** + * @classname: NoteEditActivity + * @methodname deleteCurrentNote + * @description:删除当前便签 + * @date: 2023/12/25 21:28 + * @author: Xia Yanbo + */ private void deleteCurrentNote() { - if (mWorkingNote.existInDatabase()) { - HashSet ids = new HashSet(); + if (mWorkingNote.existInDatabase()) {//检查笔记是否在数据库里 + HashSet ids = new HashSet();// 创建一个空的HashSet用于存储笔记ID long id = mWorkingNote.getNoteId(); - if (id != Notes.ID_ROOT_FOLDER) { + if (id != Notes.ID_ROOT_FOLDER) {// 如果笔记ID不是根文件夹ID,则将其添加到HashSet中 ids.add(id); - } else { + } else {// 如果笔记ID是根文件夹ID,则打印错误日志,因为这不该发生 Log.d(TAG, "Wrong note id, should not happen"); } - if (!isSyncMode()) { + if (!isSyncMode()) {// 如果不是同步模式,则执行删除操作 if (!DataUtils.batchDeleteNotes(getContentResolver(), ids)) { 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; } - + /** + * @classname: NoteEditActivity + * @methodname onClockAlertChanged + * @description: + * @date: 2023/12/25 21:34 + * @author: Xia Yanbo + * @param: + * @param: + * @param: + * @return: + */ 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()) { - saveNote(); + 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)); + AlarmManager alarmManager = ((AlarmManager) getSystemService(ALARM_SERVICE));//获取系统的闹钟服务 showAlertHeader(); - if(!set) { + if(!set) {//取消设置闹钟 alarmManager.cancel(pendingIntent); - } else { + } else {//设置闹钟 alarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent); } } else { @@ -644,26 +779,34 @@ public class NoteEditActivity extends Activity implements OnClickListener, * should input something */ Log.e(TAG, "Clock alert setting error"); - showToast(R.string.error_note_empty_for_clock); + showToast(R.string.error_note_empty_for_clock);//显示toast消息,用于提醒用户输入 } } - + //更新当前的控件 public void onWidgetChanged() { updateWidget(); } - + /** + * @classname: NoteEditActivity + * @methodname onEditTextDelete + * @description:删除正收编辑的文本 + * @date: 2023/12/25 21:41 + * @author: Xia Yanbo + * @param:text待移除的文本 + * @param:index要移除的子项的索引 + */ public void onEditTextDelete(int index, String text) { - int childCount = mEditTextList.getChildCount(); + int childCount = mEditTextList.getChildCount();//获取子项的数量 if (childCount == 1) { return; } - + // 将NoteEditText的索引更新为当前索引减1 for (int i = index + 1; i < childCount; i++) { ((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text)) .setIndex(i - 1); } - mEditTextList.removeViewAt(index); + mEditTextList.removeViewAt(index);//移除指定索引号的子项 NoteEditText edit = null; if(index == 0) { edit = (NoteEditText) mEditTextList.getChildAt(0).findViewById( @@ -677,43 +820,44 @@ public class NoteEditActivity extends Activity implements OnClickListener, edit.requestFocus(); edit.setSelection(length); } - + //文本输入换行并更新文本存储列表的索引值 public void onEditTextEnter(int index, String text) { /** * Should not happen, check for debug */ if(index > mEditTextList.getChildCount()) { - Log.e(TAG, "Index out of mEditTextList boundrary, should not happen"); + Log.e(TAG, "Index out of mEditTextList boundrary, should not happen");//超出编辑列表的边界 } - + //根据索引和文本获取列表项视图 View view = getListItem(text, index); mEditTextList.addView(view, index); NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text); - edit.requestFocus(); + edit.requestFocus();//设置焦点 edit.setSelection(0); + //文本编辑视图列表中的每一项设置索引值 for (int i = index + 1; i < mEditTextList.getChildCount(); i++) { ((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)); + mEditTextList.addView(getListItem(item, index));//添加列表项(标记:实现的关键步骤addView) index++; } } mEditTextList.addView(getListItem("", index)); mEditTextList.getChildAt(index).findViewById(R.id.et_edit_text).requestFocus(); - mNoteEditor.setVisibility(View.GONE); - mEditTextList.setVisibility(View.VISIBLE); + mNoteEditor.setVisibility(View.GONE);//用于一般模式的编辑组件隐藏 + mEditTextList.setVisibility(View.VISIBLE);//用于任务清单模式的编辑组件显示 } - + //高亮显示用户查询的关键字 private Spannable getHighlightQueryResult(String fullText, String userQuery) { SpannableString spannable = new SpannableString(fullText == null ? "" : fullText); if (!TextUtils.isEmpty(userQuery)) { @@ -721,7 +865,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, Matcher m = mPattern.matcher(fullText); int start = 0; while (m.find(start)) { - spannable.setSpan( + spannable.setSpan(//使用资源中的颜色(标记:可参考用作设计颜色) new BackgroundColorSpan(this.getResources().getColor( R.color.user_query_highlight)), m.start(), m.end(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); @@ -730,14 +874,33 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return spannable; } - + /** + * @classname: NoteEditActivity + * @methodname getListItem + * @description:根据给定的数据和索引值创建一个列表项视图 + * @date: 2023/12/26 23:52 + * @author: Xia Yanbo + * @param:item数据 + * @param:index索引值 + * @return:view 新创建的列表项视图 + */ private View getListItem(String item, int index) { + // 从当前上下文中加载NoteEditList_item布局文件,并返回一个View对象。 View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null); + + // 获取NoteEditTextView组件 final NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text); - edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId)); + + // 设置文本的外观样式,使用传入的字体大小ID作为参数。 + 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) { edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); } else { @@ -746,6 +909,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, } }); + // 根据item的开头判断是否为已选或未选,并设置相应的CheckBox状态和文本绘制样式。 if (item.startsWith(TAG_CHECKED)) { cb.setChecked(true); edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); @@ -756,24 +920,29 @@ public class NoteEditActivity extends Activity implements OnClickListener, item = item.substring(TAG_UNCHECKED.length(), item.length()).trim(); } + // 设置NoteEditTextView的监听器为当前对象(this),以便在外部进行监听和处理。 edit.setOnTextViewChangeListener(this); + // 设置NoteEditTextView的索引值。 edit.setIndex(index); + // 为NoteEditTextView设置带有高亮显示的全文文本。使用传入的用户查询作为参数。 edit.setText(getHighlightQueryResult(item, mUserQuery)); + // 返回创建的列表项视图。 return view; } - + //文本变化时进行复选框的设置 public void onTextChange(int index, boolean hasText) { if (index >= mEditTextList.getChildCount()) { Log.e(TAG, "Wrong index, should not happen"); return; } + //设置复选框的出现与否 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) { if (newMode == TextNote.MODE_CHECK_LIST) { switchToListMode(mNoteEditor.getText().toString()); @@ -787,7 +956,14 @@ public class NoteEditActivity extends Activity implements OnClickListener, mNoteEditor.setVisibility(View.VISIBLE); } } - + /** + * @classname: NoteEditActivity + * @methodname getWorkingText + * @description:对选中的文本项设置值为完成 + * @date: 2023/12/27 0:03 + * @author: Xia Yanbo + * @return:boolean表示文本项被设置成的完成状态 + */ private boolean getWorkingText() { boolean hasChecked = false; if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { @@ -806,11 +982,11 @@ public class NoteEditActivity extends Activity implements OnClickListener, } mWorkingNote.setWorkingText(sb.toString()); } else { - mWorkingNote.setWorkingText(mNoteEditor.getText().toString()); + mWorkingNote.setWorkingText(mNoteEditor.getText().toString());//不做标记值的更改 } return hasChecked; } - + //保存便签 private boolean saveNote() { getWorkingText(); boolean saved = mWorkingNote.saveNote(); @@ -826,7 +1002,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return saved; } - + //保存便签并发送到桌面 private void sendToDesktop() { /** * Before send message to home, we should make sure that current @@ -861,14 +1037,14 @@ public class NoteEditActivity extends Activity implements OnClickListener, showToast(R.string.error_note_empty_for_send_to_desktop); } } - + //生成快捷方式图标的标题 private String makeShortcutIconTitle(String content) { content = content.replace(TAG_CHECKED, ""); content = content.replace(TAG_UNCHECKED, ""); return content.length() > SHORTCUT_ICON_TITLE_MAX_LEN ? content.substring(0, SHORTCUT_ICON_TITLE_MAX_LEN) : content; } - + //消息传递 private void showToast(int resId) { showToast(resId, Toast.LENGTH_SHORT); } diff --git a/src/main/java/net/micode/notes/ui/NoteEditText.java b/src/main/java/net/micode/notes/ui/NoteEditText.java index 39592b5..34fc9dd 100644 --- a/src/main/java/net/micode/notes/ui/NoteEditText.java +++ b/src/main/java/net/micode/notes/ui/NoteEditText.java @@ -38,14 +38,11 @@ import java.util.HashMap; import java.util.Map; /** * @classname: NoteEditText - * @methodname - * @description: + * @description:NoteEditText继承了 EditText父类 + * 负责开启监听以完成文本的读取,并做出相应的处理动作 + * 同时还负责上下文菜单的创建 * @date: 2023/12/24 9:22 * @author: Xia Yanbo - * @param: - * @param: - * @param: - * @return: */ public class NoteEditText extends EditText { private static final String TAG = "NoteEditText";//标签,分类接收特定信息