|
|
|
@ -15,7 +15,7 @@
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package net.micode.notes.ui;
|
|
|
|
|
|
|
|
|
|
// 这里假设你的包名是com.example.yourpackage,实际需替换为正确的包名
|
|
|
|
|
import android.app.Activity;
|
|
|
|
|
import android.app.AlarmManager;
|
|
|
|
|
import android.app.AlertDialog;
|
|
|
|
@ -71,19 +71,23 @@ import java.util.Map;
|
|
|
|
|
import java.util.regex.Matcher;
|
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// NoteEditActivity类,继承自Activity(或AppCompatActivity,取决于实际的父类继承情况),实现了多个接口,用于处理笔记编辑相关的各种交互逻辑,
|
|
|
|
|
// 例如点击事件、设置变更监听、文本变更监听等,是一个用于编辑笔记的Activity
|
|
|
|
|
public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
NoteSettingChangedListener, OnTextViewChangeListener {
|
|
|
|
|
// 内部类HeadViewHolder,用于封装笔记头部视图相关的UI组件,方便管理和操作
|
|
|
|
|
private class HeadViewHolder {
|
|
|
|
|
public TextView tvModified;
|
|
|
|
|
|
|
|
|
|
// 用于显示笔记修改时间的TextView组件
|
|
|
|
|
public ImageView ivAlertIcon;
|
|
|
|
|
|
|
|
|
|
// 用于显示提醒图标(如闹钟图标等)的ImageView组件
|
|
|
|
|
public TextView tvAlertDate;
|
|
|
|
|
|
|
|
|
|
// 用于显示提醒时间相关信息的TextView组件
|
|
|
|
|
public ImageView ibSetBgColor;
|
|
|
|
|
// 用于设置背景颜色的ImageView按钮组件
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 静态的Map,用于将背景颜色选择按钮的资源ID(如R.id.iv_bg_yellow等)映射到对应的颜色常量(如ResourceParser.YELLOW等),方便根据按钮ID获取对应的颜色标识
|
|
|
|
|
private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>();
|
|
|
|
|
static {
|
|
|
|
|
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
|
|
|
|
@ -93,6 +97,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
sBgSelectorBtnsMap.put(R.id.iv_bg_white, ResourceParser.WHITE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 静态的Map,用于将颜色常量(如ResourceParser.YELLOW等)映射到对应的背景颜色选择按钮被选中时的显示资源ID(如R.id.iv_bg_yellow_select等),
|
|
|
|
|
// 用于在选择颜色后显示相应的选中效果
|
|
|
|
|
private static final Map<Integer, Integer> sBgSelectorSelectionMap = new HashMap<Integer, Integer>();
|
|
|
|
|
static {
|
|
|
|
|
sBgSelectorSelectionMap.put(ResourceParser.YELLOW, R.id.iv_bg_yellow_select);
|
|
|
|
@ -102,6 +108,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 静态的Map,用于将字体大小选择按钮所在的布局资源ID(如R.id.ll_font_large等)映射到对应的字体大小常量(如ResourceParser.TEXT_LARGE等),方便根据按钮布局ID获取对应的字体大小标识
|
|
|
|
|
private static final Map<Integer, Integer> sFontSizeBtnsMap = new HashMap<Integer, Integer>();
|
|
|
|
|
static {
|
|
|
|
|
sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE);
|
|
|
|
@ -110,6 +117,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
sFontSizeBtnsMap.put(R.id.ll_font_super, ResourceParser.TEXT_SUPER);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 静态的Map,用于将字体大小常量(如ResourceParser.TEXT_LARGE等)映射到对应的字体大小选择按钮被选中时的显示资源ID(如R.id.iv_large_select等),
|
|
|
|
|
// 用于在选择字体大小后显示相应的选中效果
|
|
|
|
|
private static final Map<Integer, Integer> sFontSelectorSelectionMap = new HashMap<Integer, Integer>();
|
|
|
|
|
static {
|
|
|
|
|
sFontSelectorSelectionMap.put(ResourceParser.TEXT_LARGE, R.id.iv_large_select);
|
|
|
|
@ -118,46 +127,68 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SUPER, R.id.iv_super_select);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 用于日志记录的标签,方便在日志中识别该Activity相关的输出信息
|
|
|
|
|
private static final String TAG = "NoteEditActivity";
|
|
|
|
|
|
|
|
|
|
// 用于存储笔记头部视图相关组件的实例,方便后续操作和更新头部视图的显示内容
|
|
|
|
|
private HeadViewHolder mNoteHeaderHolder;
|
|
|
|
|
|
|
|
|
|
// 笔记头部视图的整体布局,包含标题、修改时间、提醒相关等组件的外层容器
|
|
|
|
|
private View mHeadViewPanel;
|
|
|
|
|
|
|
|
|
|
// 用于显示背景颜色选择器的视图,包含各种背景颜色选项按钮等
|
|
|
|
|
private View mNoteBgColorSelector;
|
|
|
|
|
|
|
|
|
|
// 用于显示字体大小选择器的视图,包含各种字体大小选项按钮等
|
|
|
|
|
private View mFontSizeSelector;
|
|
|
|
|
|
|
|
|
|
// 用于编辑笔记内容的EditText组件,用户在此输入和修改笔记的文本内容
|
|
|
|
|
private EditText mNoteEditor;
|
|
|
|
|
|
|
|
|
|
// 包含笔记编辑区域(如mNoteEditor)以及相关滚动等功能的外层布局视图,用于整体的笔记编辑界面布局管理
|
|
|
|
|
private View mNoteEditorPanel;
|
|
|
|
|
|
|
|
|
|
// 代表正在编辑的笔记对象,包含笔记的各种属性(如内容、修改时间、背景颜色等)以及相关操作方法(如保存、加载等)
|
|
|
|
|
private WorkingNote mWorkingNote;
|
|
|
|
|
|
|
|
|
|
// 用于获取和操作应用的共享偏好设置,可用于存储和读取如字体大小、用户个性化设置等相关信息
|
|
|
|
|
private SharedPreferences mSharedPrefs;
|
|
|
|
|
|
|
|
|
|
// 当前选择的字体大小ID,对应于ResourceParser中定义的字体大小常量,用于确定笔记编辑区域显示的字体大小
|
|
|
|
|
private int mFontSizeId;
|
|
|
|
|
|
|
|
|
|
// 存储在共享偏好设置中用于标识字体大小偏好设置的键名常量
|
|
|
|
|
private static final String PREFERENCE_FONT_SIZE = "pref_font_size";
|
|
|
|
|
|
|
|
|
|
// 快捷方式图标标题的最大长度限制,用于生成发送到桌面的快捷方式图标时,截取合适长度的笔记内容作为标题
|
|
|
|
|
private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10;
|
|
|
|
|
|
|
|
|
|
// 表示复选框被选中状态的字符常量,用于处理复选框列表模式下的笔记内容显示和解析
|
|
|
|
|
public static final String TAG_CHECKED = String.valueOf('\u221A');
|
|
|
|
|
// 表示复选框未被选中状态的字符常量,用于处理复选框列表模式下的笔记内容显示和解析
|
|
|
|
|
public static final String TAG_UNCHECKED = String.valueOf('\u25A1');
|
|
|
|
|
|
|
|
|
|
// 用于存储笔记编辑中多行文本(如果是列表模式等情况)的LinearLayout,每个子项可能是一个包含文本和复选框的自定义布局,方便处理多行文本编辑逻辑
|
|
|
|
|
private LinearLayout mEditTextList;
|
|
|
|
|
|
|
|
|
|
// 用户查询的文本内容,可能用于搜索、筛选等功能相关,比如在笔记中查找特定内容等场景
|
|
|
|
|
private String mUserQuery;
|
|
|
|
|
// 用于正则表达式匹配的Pattern对象,可能用于在笔记内容中按照特定规则查找、匹配文本等操作,具体取决于业务逻辑中如何使用
|
|
|
|
|
private Pattern mPattern;
|
|
|
|
|
|
|
|
|
|
// Activity创建时调用的方法,进行一些初始化操作,如设置布局、恢复Activity状态等
|
|
|
|
|
@Override
|
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
// 设置该Activity对应的布局文件,即加载笔记编辑界面的UI布局
|
|
|
|
|
this.setContentView(R.layout.note_edit);
|
|
|
|
|
|
|
|
|
|
// 如果是首次创建(savedInstanceState为null)且初始化Activity状态失败,则直接结束该Activity并返回
|
|
|
|
|
if (savedInstanceState == null && !initActivityState(getIntent())) {
|
|
|
|
|
finish();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 初始化各种资源,如查找UI组件、设置点击事件监听器等
|
|
|
|
|
initResources();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -168,6 +199,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
@Override
|
|
|
|
|
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
|
|
|
|
super.onRestoreInstanceState(savedInstanceState);
|
|
|
|
|
// 如果保存的实例状态不为null且包含特定的用户ID信息(通过Intent.EXTRA_UID标识),则尝试恢复Activity状态
|
|
|
|
|
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));
|
|
|
|
@ -179,16 +211,21 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 根据传入的Intent初始化Activity的状态,根据不同的Intent动作(如查看、新建/编辑等)来加载相应的笔记数据或者创建新的笔记对象
|
|
|
|
|
private boolean initActivityState(Intent intent) {
|
|
|
|
|
// 初始化正在编辑的笔记对象为null
|
|
|
|
|
/**
|
|
|
|
|
* If the user specified the {@link Intent#ACTION_VIEW} but not provided with id,
|
|
|
|
|
* then jump to the NotesListActivity
|
|
|
|
|
*/
|
|
|
|
|
mWorkingNote = null;
|
|
|
|
|
// 如果Intent的动作是查看笔记(Intent.ACTION_VIEW)
|
|
|
|
|
if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) {
|
|
|
|
|
// 获取笔记的ID,如果没有传入则默认为0
|
|
|
|
|
long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0);
|
|
|
|
|
mUserQuery = "";
|
|
|
|
|
|
|
|
|
|
// 如果Intent中包含搜索结果相关的额外数据(通过SearchManager.EXTRA_DATA_KEY标识),则更新笔记ID和用户查询文本
|
|
|
|
|
/**
|
|
|
|
|
* Starting from the searched result
|
|
|
|
|
*/
|
|
|
|
@ -197,6 +234,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查该笔记ID对应的笔记在数据库中是否可见(是否存在且满足一定可见条件),如果不可见,则跳转到笔记列表页面,并提示笔记不存在,然后结束当前Activity
|
|
|
|
|
if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) {
|
|
|
|
|
Intent jump = new Intent(this, NotesListActivity.class);
|
|
|
|
|
startActivity(jump);
|
|
|
|
@ -204,6 +242,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
finish();
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
// 从数据库加载对应笔记ID的笔记对象,如果加载失败则记录错误日志并结束当前Activity
|
|
|
|
|
mWorkingNote = WorkingNote.load(this, noteId);
|
|
|
|
|
if (mWorkingNote == null) {
|
|
|
|
|
Log.e(TAG, "load note failed with note id" + noteId);
|
|
|
|
@ -211,19 +250,28 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
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())) {
|
|
|
|
|
// 如果Intent的动作是新建或编辑笔记(Intent.ACTION_INSERT_OR_EDIT)
|
|
|
|
|
|
|
|
|
|
// 获取文件夹ID,如果没有传入则默认为0
|
|
|
|
|
// New note
|
|
|
|
|
long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0);
|
|
|
|
|
// 获取小部件ID,如果没有传入则默认为无效的小部件ID(AppWidgetManager.INVALID_APPWIDGET_ID)
|
|
|
|
|
int widgetId = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_ID,
|
|
|
|
|
AppWidgetManager.INVALID_APPWIDGET_ID);
|
|
|
|
|
// 获取小部件类型,如果没有传入则默认为无效的小部件类型(Notes.TYPE_WIDGET_INVALIDE)
|
|
|
|
|
int widgetType = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_TYPE,
|
|
|
|
|
Notes.TYPE_WIDGET_INVALIDE);
|
|
|
|
|
// 获取背景资源ID,如果没有传入则调用ResourceParser获取默认的背景颜色资源ID
|
|
|
|
|
int bgResId = intent.getIntExtra(Notes.INTENT_EXTRA_BACKGROUND_ID,
|
|
|
|
|
ResourceParser.getDefaultBgId(this));
|
|
|
|
|
|
|
|
|
|
// 解析通话记录笔记相关信息,如果Intent中包含电话号码和通话日期,则尝试根据这些信息获取对应的笔记ID,
|
|
|
|
|
// 如果找到对应笔记ID则加载该笔记对象,否则创建一个空的笔记对象并转换为通话笔记格式
|
|
|
|
|
// Parse call-record note
|
|
|
|
|
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
|
|
|
|
|
long callDate = intent.getLongExtra(Notes.INTENT_EXTRA_CALL_DATE, 0);
|
|
|
|
@ -241,11 +289,15 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 如果没有通话记录相关信息,则创建一个空的笔记对象
|
|
|
|
|
mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId,
|
|
|
|
|
widgetType, bgResId);
|
|
|
|
|
mWorkingNote.convertToCallNote(phoneNumber, callDate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置软键盘的显示模式,初始显示软键盘并且根据内容调整布局大小
|
|
|
|
|
} else {
|
|
|
|
|
// 如果Intent没有指定有效的动作,则记录错误日志并结束当前Activity,因为不支持这种情况
|
|
|
|
|
mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId, widgetType,
|
|
|
|
|
bgResId);
|
|
|
|
|
}
|
|
|
|
@ -258,66 +310,96 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
finish();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置正在编辑的笔记对象的设置状态变更监听器为当前Activity(实现了NoteSettingChangedListener接口)
|
|
|
|
|
mWorkingNote.setOnSettingStatusChangedListener(this);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Activity重新恢复到前台可见时调用的方法,用于重新初始化笔记编辑界面的显示内容等
|
|
|
|
|
@Override
|
|
|
|
|
protected void onResume() {
|
|
|
|
|
super.onResume();
|
|
|
|
|
initNoteScreen();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 初始化笔记编辑界面的显示内容,如设置字体大小、根据笔记模式(是否为复选框列表模式等)显示相应内容、更新头部视图的时间显示等
|
|
|
|
|
private void initNoteScreen() {
|
|
|
|
|
// 设置笔记编辑区域的文本外观,根据当前选择的字体大小ID获取对应的文本外观资源并应用
|
|
|
|
|
mNoteEditor.setTextAppearance(this, TextAppearanceResources
|
|
|
|
|
.getTexAppearanceResource(mFontSizeId));
|
|
|
|
|
|
|
|
|
|
// 如果笔记处于复选框列表模式,则切换到列表模式显示界面,并传入笔记内容进行相应处理
|
|
|
|
|
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
|
|
|
|
|
switchToListMode(mWorkingNote.getContent());
|
|
|
|
|
} else {
|
|
|
|
|
// 如果不是列表模式,则在编辑区域显示笔记内容,并对用户查询的文本进行高亮显示,然后将光标定位到文本末尾
|
|
|
|
|
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
|
|
|
|
|
mNoteEditor.setSelection(mNoteEditor.getText().length());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 遍历背景颜色选择按钮选中状态对应的资源ID映射表,将所有选中状态的显示组件设置为不可见,用于清除之前可能的选中显示效果
|
|
|
|
|
for (Integer id : sBgSelectorSelectionMap.keySet()) {
|
|
|
|
|
findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置笔记头部视图的背景资源,根据正在编辑的笔记对象获取对应的标题背景资源ID并应用
|
|
|
|
|
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
|
|
|
|
|
// 设置笔记编辑区域的背景资源,根据正在编辑的笔记对象获取对应的背景颜色资源ID并应用
|
|
|
|
|
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置笔记头部视图中修改时间的显示文本,根据笔记的修改时间格式化并显示相应的日期和时间信息
|
|
|
|
|
mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(this,
|
|
|
|
|
mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
|
|
|
|
|
| DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
|
|
|
|
|
| DateUtils.FORMAT_SHOW_YEAR));
|
|
|
|
|
// 显示提醒相关的头部信息(如提醒图标和提醒时间等),根据笔记是否设置了提醒以及当前时间等情况进行相应的显示
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* TODO: Add the menu for setting alert. Currently disable it because the DateTimePicker
|
|
|
|
|
* is not ready
|
|
|
|
|
*/
|
|
|
|
|
// 显示提醒相关的头部信息(如提醒图标和提醒时间等),根据笔记是否设置了提醒以及当前时间等情况进行相应的显示
|
|
|
|
|
showAlertHeader();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 此方法用于根据笔记是否设置了提醒以及当前时间与提醒时间的关系,来设置笔记头部提醒相关视图(提醒时间文本和提醒图标)的显示状态及内容
|
|
|
|
|
private void showAlertHeader() {
|
|
|
|
|
private void showAlertHeader() {
|
|
|
|
|
// 判断正在编辑的笔记对象(mWorkingNote)是否设置了时钟提醒(hasClockAlert方法返回true表示设置了提醒)
|
|
|
|
|
if (mWorkingNote.hasClockAlert()) {
|
|
|
|
|
// 获取当前系统时间(以毫秒为单位,从1970年1月1日00:00:00 UTC到当前时间的毫秒数)
|
|
|
|
|
long time = System.currentTimeMillis();
|
|
|
|
|
// 如果当前时间大于笔记设置的提醒时间
|
|
|
|
|
if (time > mWorkingNote.getAlertDate()) {
|
|
|
|
|
// 将提醒时间文本视图(mNoteHeaderHolder.tvAlertDate)的内容设置为表示提醒已过期的字符串资源(R.string.note_alert_expired
|
|
|
|
|
mNoteHeaderHolder.tvAlertDate.setText(R.string.note_alert_expired);
|
|
|
|
|
} else {
|
|
|
|
|
// 如果当前时间未超过提醒时间,则调用DateUtils的方法获取相对时间跨度字符串,用于显示距离提醒时间还有多久,
|
|
|
|
|
// 参数分别为提醒时间、当前时间以及时间跨度的单位(这里是以分钟为单位,DateUtils.MINUTE_IN_MILLIS表示一分钟对应的毫秒数)
|
|
|
|
|
mNoteHeaderHolder.tvAlertDate.setText(DateUtils.getRelativeTimeSpanString(
|
|
|
|
|
mWorkingNote.getAlertDate(), time, DateUtils.MINUTE_IN_MILLIS));
|
|
|
|
|
}
|
|
|
|
|
// 将提醒时间文本视图设置为可见状态,以便用户能看到提醒相关的时间信息
|
|
|
|
|
mNoteHeaderHolder.tvAlertDate.setVisibility(View.VISIBLE);
|
|
|
|
|
// 将提醒图标视图设置为可见状态,展示相应的提醒图标,提示用户有提醒设置
|
|
|
|
|
mNoteHeaderHolder.ivAlertIcon.setVisibility(View.VISIBLE);
|
|
|
|
|
} else {
|
|
|
|
|
// 如果笔记没有设置时钟提醒,则将提醒时间文本视图设置为不可见状态,隐藏相关文本显示
|
|
|
|
|
mNoteHeaderHolder.tvAlertDate.setVisibility(View.GONE);
|
|
|
|
|
// 将提醒图标视图设置为不可见状态,隐藏提醒图标
|
|
|
|
|
mNoteHeaderHolder.ivAlertIcon.setVisibility(View.GONE);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当Activity接收到新的Intent时会调用此方法,它首先调用父类的onNewIntent方法,然后根据新传入的Intent重新初始化Activity的状态
|
|
|
|
|
@Override
|
|
|
|
|
protected void onNewIntent(Intent intent) {
|
|
|
|
|
super.onNewIntent(intent);
|
|
|
|
|
// 调用initActivityState方法,传入新的Intent,根据Intent中的信息来重新加载笔记数据、设置相关属性等,以适应新的启动意图,
|
|
|
|
|
// 比如从其他地方重新启动该Activity并传递了不同的参数,就会在此处更新Activity的状态
|
|
|
|
|
initActivityState(intent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当系统即将销毁Activity以回收内存或者进行配置变更(如屏幕旋转)等情况时,会调用此方法来保存Activity的当前状态信息,
|
|
|
|
|
// 以便后续可以恢复到当前状态。这里先调用父类的onSaveInstanceState方法来执行默认的保存操作,然后进行自定义的保存逻辑
|
|
|
|
|
@Override
|
|
|
|
|
protected void onSaveInstanceState(Bundle outState) {
|
|
|
|
|
super.onSaveInstanceState(outState);
|
|
|
|
@ -328,51 +410,73 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
*/
|
|
|
|
|
if (!mWorkingNote.existInDatabase()) {
|
|
|
|
|
saveNote();
|
|
|
|
|
// 将正在编辑的笔记对象的ID存入传出的Bundle(outState)中,键为Intent.EXTRA_UID,以便后续恢复状态时能获取到该笔记的标识信息
|
|
|
|
|
}
|
|
|
|
|
outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId());
|
|
|
|
|
// 在日志中记录正在保存的工作笔记的ID信息,方便调试和查看状态保存情况,使用TAG作为日志标签方便识别是该Activity相关的日志输出
|
|
|
|
|
Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 用于分发触摸事件,Activity接收到触摸事件后会先经过此方法处理,在这里可以拦截触摸事件或者将其传递给子视图进行处理。
|
|
|
|
|
// 主要用于处理背景颜色选择器和字体大小选择器在显示时,触摸事件在其范围外的情况
|
|
|
|
|
@Override
|
|
|
|
|
public boolean dispatchTouchEvent(MotionEvent ev) {
|
|
|
|
|
// 如果背景颜色选择器(mNoteBgColorSelector)当前处于可见状态,并且触摸事件不在其显示范围内(通过inRangeOfView方法判断)
|
|
|
|
|
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE
|
|
|
|
|
&& !inRangeOfView(mNoteBgColorSelector, ev)) {
|
|
|
|
|
// 则将背景颜色选择器设置为不可见,隐藏该选择器视
|
|
|
|
|
mNoteBgColorSelector.setVisibility(View.GONE);
|
|
|
|
|
// 返回true表示已经处理了该触摸事件,不会再继续传递给其他视图进行处理,即拦截了此次触摸事件对背景颜色选择器的后续影响
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mFontSizeSelector.getVisibility() == View.VISIBLE
|
|
|
|
|
&& !inRangeOfView(mFontSizeSelector, ev)) {
|
|
|
|
|
// 将字体大小选择器设置为不可见,隐藏该选择器视图
|
|
|
|
|
mFontSizeSelector.setVisibility(View.GONE);
|
|
|
|
|
// 返回true表示已经处理了该触摸事件,拦截了此次触摸事件对字体大小选择器的后续影响,不再继续传递给其他视图
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
// 如果上述条件都不满足,即触摸事件不在需要特殊处理的选择器范围外,或者选择器本身就不可见等情况,
|
|
|
|
|
// 则调用父类的dispatchTouchEvent方法,将触摸事件按照默认的分发逻辑继续传递给其他视图进行处理
|
|
|
|
|
return super.dispatchTouchEvent(ev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 此方法用于判断给定的触摸事件(MotionEvent)是否在指定的视图(view)范围内,通过比较触摸点的坐标与视图在屏幕上的坐标及尺寸来确定
|
|
|
|
|
private boolean inRangeOfView(View view, MotionEvent ev) {
|
|
|
|
|
int []location = new int[2];
|
|
|
|
|
// 获取指定视图在屏幕上的坐标位置,将结果存入location数组中,通过这种方式可以得到视图左上角顶点相对于屏幕左上角的坐标值
|
|
|
|
|
view.getLocationOnScreen(location);
|
|
|
|
|
// 获取视图在屏幕上的横坐标(x坐标),即location数组的第一个元素
|
|
|
|
|
int x = location[0];
|
|
|
|
|
// 获取视图在屏幕上的纵坐标(y坐标),即location数组的第二个元素
|
|
|
|
|
int y = location[1];
|
|
|
|
|
// 判断触摸事件的横坐标(ev.getX()获取触摸点相对于触发触摸事件的视图的横坐标)是否小于视图的横坐标(x),
|
|
|
|
|
// 如果小于则说明触摸点在视图的左侧,不在视图范围内,返回false
|
|
|
|
|
if (ev.getX() < x
|
|
|
|
|
|| ev.getX() > (x + view.getWidth())
|
|
|
|
|
|| ev.getY() < y
|
|
|
|
|
|| ev.getY() > (y + view.getHeight())) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断触摸事件的横坐标是否大于视图的横坐标加上视图的宽度(x + view.getWidth()表示视图的右侧边界横坐标),
|
|
|
|
|
// 如果大于则说明触摸点在视图的右侧,不在视图范围内,返回false
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 判断触摸事件的纵坐标(ev.getY()获取触摸点相对于触发触摸事件的视图的纵坐标)是否小于视图的纵坐标(y),
|
|
|
|
|
// 如果小于则说明触摸点在视图的上方,不在视图范围内,返回false
|
|
|
|
|
private void initResources() {
|
|
|
|
|
mHeadViewPanel = findViewById(R.id.note_title);
|
|
|
|
|
// 创建一个HeadViewHolder实例,用于存储笔记头部视图相关的各个子组件,方便后续统一操作和管理这些组件
|
|
|
|
|
mNoteHeaderHolder = new HeadViewHolder();
|
|
|
|
|
// 通过findViewById方法查找布局文件中ID为tv_modified_date的TextView组件,该组件通常用于显示笔记的修改时间,
|
|
|
|
|
// 并将其赋值给mNoteHeaderHolder中的tvModified变量,方便后续操作该文本视图(如设置显示的文本内容等)
|
|
|
|
|
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);
|
|
|
|
|
mNoteEditor = (EditText) findViewById(R.id.note_edit_view);
|
|
|
|
|
mNoteEditorPanel = findViewById(R.id.sv_note_edit);
|
|
|
|
|
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);
|
|
|
|
@ -397,15 +501,20 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当Activity失去焦点即将进入暂停状态时调用此方法,例如用户切换到其他应用或者按下Home键等情况。
|
|
|
|
|
// 先调用父类的onPause方法执行默认的暂停操作,然后进行自定义的保存笔记数据和清理设置状态相关操作
|
|
|
|
|
@Override
|
|
|
|
|
protected void onPause() {
|
|
|
|
|
super.onPause();
|
|
|
|
|
// 调用saveNote方法保存笔记数据,如果保存成功(saveNote方法返回true)
|
|
|
|
|
if(saveNote()) {
|
|
|
|
|
Log.d(TAG, "Note data was saved with length:" + mWorkingNote.getContent().length());
|
|
|
|
|
}
|
|
|
|
|
clearSettingState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 用于更新桌面小部件的显示内容,根据正在编辑的笔记对象(mWorkingNote)的小部件类型,
|
|
|
|
|
// 构建相应的Intent并发送广播通知系统更新对应的小部件显示
|
|
|
|
|
private void updateWidget() {
|
|
|
|
|
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
|
|
|
|
|
if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) {
|
|
|
|
@ -417,10 +526,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 将正在编辑的笔记对象的小部件ID添加到Intent的额外数据中,键为AppWidgetManager.EXTRA_APPWIDGET_IDS,
|
|
|
|
|
// 这样接收广播的小部件更新逻辑可以知道要更新哪个具体的小部件实例
|
|
|
|
|
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
|
|
|
|
|
mWorkingNote.getWidgetId()
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 处理界面上各个视图的点击事件,根据点击的视图ID来执行相应的操作逻辑,例如显示或隐藏相关视图、更新笔记的属性(如背景颜色、字体大小等)
|
|
|
|
|
sendBroadcast(intent);
|
|
|
|
|
setResult(RESULT_OK, intent);
|
|
|
|
|
}
|
|
|
|
@ -452,12 +564,17 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当用户按下返回键时调用此方法,先尝试清理设置状态(如隐藏背景颜色选择器、字体大小选择器等),
|
|
|
|
|
// 如果清理成功则直接返回,不再执行默认的返回操作;如果清理失败则先保存笔记数据,再执行默认的返回操作
|
|
|
|
|
@Override
|
|
|
|
|
public void onBackPressed() {
|
|
|
|
|
if(clearSettingState()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 用于清理设置状态,检查背景颜色选择器和字体大小选择器是否处于可见状态,如果处于可见则将其设置为不可见,
|
|
|
|
|
// 根据是否有进行隐藏操作来返回相应的布尔值(true表示有隐藏操作,false表示没有需要隐藏的视图)
|
|
|
|
|
// 如果清理设置状态失败,则调用saveNote方法保存笔记数据
|
|
|
|
|
saveNote();
|
|
|
|
|
super.onBackPressed();
|
|
|
|
|
}
|
|
|
|
@ -473,13 +590,19 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当笔记的背景颜色发生改变时调用此方法,用于更新界面上相关视图的显示,以反映背景颜色的变化,
|
|
|
|
|
// 例如显示对应的背景颜色选中状态提示、设置笔记编辑区域和头部视图的背景资源等
|
|
|
|
|
public void onBackgroundColorChanged() {
|
|
|
|
|
// 根据正在编辑的笔记对象(mWorkingNote)当前的背景颜色ID,找到对应的背景颜色选择按钮选中状态显示的视图,并将其设置为可见状态,
|
|
|
|
|
// 用于提示用户当前选择的是哪种背景颜色(显示选中效果)
|
|
|
|
|
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
|
|
|
|
|
View.VISIBLE);
|
|
|
|
|
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
|
|
|
|
|
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 在准备显示选项菜单(Options Menu)时调用此方法,进行一些菜单相关的初始化操作,例如清理菜单、根据笔记的属性(如是否为通话记录笔记、是否有提醒等)加载不同的菜单布局、
|
|
|
|
|
// 更新菜单项的标题显示等,最后返回true表示菜单准备就绪可以显示
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
|
|
|
|
if (isFinishing()) {
|
|
|
|
@ -505,10 +628,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理选项菜单中各个菜单项的点击事件,根据点击的菜单项ID来执行相应的操作逻辑,例如创建新笔记、删除笔记、设置提醒、分享笔记等
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
|
case R.id.menu_new_note:
|
|
|
|
|
// 如果点击的菜单项是“新建笔记”(menu_new_note),则调用createNewNote方法创建一个新的笔记
|
|
|
|
|
createNewNote();
|
|
|
|
|
break;
|
|
|
|
|
case R.id.menu_delete:
|
|
|
|
@ -523,6 +648,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
finish();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// 设置对话框的“取消”按钮(NegativeButton),点击时不执行任何操作(传入null)
|
|
|
|
|
builder.setNegativeButton(android.R.string.cancel, null);
|
|
|
|
|
builder.show();
|
|
|
|
|
break;
|
|
|
|
@ -531,10 +657,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);
|
|
|
|
|
break;
|
|
|
|
|
case R.id.menu_list_mode:
|
|
|
|
|
// 如果点击的菜单项是“列表模式”(menu_list_mode),则切换正在编辑的笔记对象的复选框列表模式状态,
|
|
|
|
|
// 如果当前是普通模式(getCheckListMode返回0)则切换为复选框列表模式(TextNote.MODE_CHECK_LIST),否则切换回普通模式(0)
|
|
|
|
|
mWorkingNote.setCheckListMode(mWorkingNote.getCheckListMode() == 0 ?
|
|
|
|
|
TextNote.MODE_CHECK_LIST : 0);
|
|
|
|
|
break;
|
|
|
|
|
case R.id.menu_share:
|
|
|
|
|
// 如果点击的菜单项是“分享”(menu_share),则先调用getWorkingText方法获取笔记的文本内容,
|
|
|
|
|
// 然后调用sendTo方法将笔记内容分享到支持Intent.ACTION_SEND动作且类型为text/plain的其他应用中
|
|
|
|
|
getWorkingText();
|
|
|
|
|
sendTo(this, mWorkingNote.getContent());
|
|
|
|
|
break;
|
|
|
|
@ -554,7 +684,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void setReminder() {
|
|
|
|
|
// 创建一个DateTimePickerDialog实例,用于显示日期时间选择对话框,传入当前Activity的上下文
|
|
|
|
|
DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis());
|
|
|
|
|
// 为DateTimePickerDialog设置日期时间设置监听器,当用户在对话框中选择好日期时间并点击确定后,会触发该监听器的OnDateTimeSet方法。
|
|
|
|
|
d.setOnDateTimeSetListener(new OnDateTimeSetListener() {
|
|
|
|
|
public void OnDateTimeSet(AlertDialog dialog, long date) {
|
|
|
|
|
mWorkingNote.setAlertDate(date , true);
|
|
|
|
@ -563,6 +695,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
d.show();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 此方法用于将笔记内容分享到支持指定Intent动作(Intent.ACTION_SEND)和文本类型(text/plain)的其他应用中,比如分享到短信、邮件等应用。
|
|
|
|
|
/**
|
|
|
|
|
* Share note to apps that support {@link Intent#ACTION_SEND} action
|
|
|
|
|
* and {@text/plain} type
|
|
|
|
@ -574,6 +707,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
context.startActivity(intent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 此方法用于创建一个新的笔记,操作流程为先保存当前正在编辑的笔记(如果有),然后关闭当前的NoteEditActivity,再启动一个新的NoteEditActivity进入新建笔记的流程。
|
|
|
|
|
private void createNewNote() {
|
|
|
|
|
// Firstly, save current editing notes
|
|
|
|
|
saveNote();
|
|
|
|
@ -586,6 +720,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
startActivity(intent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 此方法用于删除当前正在编辑的笔记,根据笔记是否存在于数据库以及当前应用是否处于同步模式等情况
|
|
|
|
|
private void deleteCurrentNote() {
|
|
|
|
|
if (mWorkingNote.existInDatabase()) {
|
|
|
|
|
HashSet<Long> ids = new HashSet<Long>();
|
|
|
|
@ -608,10 +743,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
mWorkingNote.markDeleted(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 此方法用于判断当前应用是否处于同步模式,通过获取同步账户名称(调用NotesPreferenceActivity的getSyncAccountName方法)并检查其去除空格后的长度是否大于0来确定。
|
|
|
|
|
private boolean isSyncMode() {
|
|
|
|
|
return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 此方法用于处理笔记的时钟提醒相关设置的变更,例如设置或取消提醒时间等操作,在操作前会先确保笔记已保存(如果未保存则先保存),然后根据不同情况与系统的闹钟服务(AlarmManager)交互来设置或取消提醒。
|
|
|
|
|
public void onClockAlertChanged(long date, boolean set) {
|
|
|
|
|
/**
|
|
|
|
|
* User could set clock to an unsaved note, so before setting the
|
|
|
|
@ -642,10 +779,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 此方法用于处理在笔记编辑的多行文本列表中删除某一行文本的操作,会调整后续行的索引,并将删除行的文本内容合并到前一行(如果是第一行则直接处理该行),同时更新焦点和光标位置等。
|
|
|
|
|
public void onWidgetChanged() {
|
|
|
|
|
updateWidget();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 遍历从要删除行的下一行(index + 1)开始到最后一行的所有行,调整它们的索引,将其索引减1,使其与新的行数顺序对应。
|
|
|
|
|
public void onEditTextDelete(int index, String text) {
|
|
|
|
|
int childCount = mEditTextList.getChildCount();
|
|
|
|
|
if (childCount == 1) {
|
|
|
|
@ -657,6 +796,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
.setIndex(i - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从多行文本列表中移除指定索引(index)的行视图。
|
|
|
|
|
mEditTextList.removeViewAt(index);
|
|
|
|
|
NoteEditText edit = null;
|
|
|
|
|
if(index == 0) {
|
|
|
|
@ -672,6 +812,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
edit.setSelection(length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 此方法用于处理在笔记编辑的多行文本列表中插入一行新文本的操作,会在指定索引位置添加新的行视图,更新相关行的索引,并设置新行的文本内容、焦点以及光标位置等。
|
|
|
|
|
public void onEditTextEnter(int index, String text) {
|
|
|
|
|
/**
|
|
|
|
|
* Should not happen, check for debug
|
|
|
|
@ -691,7 +832,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void switchToListMode(String text) {
|
|
|
|
|
// 首先移除多行文本列表(mEditTextList)中已有的所有视图,清空列表内容,为重新构建列表做准备。
|
|
|
|
|
mEditTextList.removeAllViews();
|
|
|
|
|
String[] items = text.split("\n");
|
|
|
|
|
int index = 0;
|
|
|
|
@ -701,17 +844,24 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
index++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 在多行文本列表末尾添加一个空的列表项视图,可能用于方便用户后续继续添加新的内容,提供一个空白的可编辑项。
|
|
|
|
|
mEditTextList.addView(getListItem("", index));
|
|
|
|
|
// 获取多行文本列表中最后一个添加的列表项(即索引为 index 的项)中的文本编辑框(NoteEditText)组件,并请求获取焦点,
|
|
|
|
|
// 使得用户切换到列表模式后,光标默认处于最后一个可编辑项处,方便用户直接输入内容。
|
|
|
|
|
mEditTextList.getChildAt(index).findViewById(R.id.et_edit_text).requestFocus();
|
|
|
|
|
|
|
|
|
|
mNoteEditor.setVisibility(View.GONE);
|
|
|
|
|
mEditTextList.setVisibility(View.VISIBLE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 此方法用于在给定的完整文本(fullText)中,根据用户输入的查询文本(userQuery)查找匹配的内容,并将匹配的内容设置为高亮显示,最后返回处理后的包含高亮显示效果的 Spannable 对象。
|
|
|
|
|
private Spannable getHighlightQueryResult(String fullText, String userQuery) {
|
|
|
|
|
// 创建一个 SpannableString 对象,将传入的完整文本(如果传入的 fullText 为 null,则初始化为空字符串)包装起来,
|
|
|
|
|
// 以便后续可以对其内容进行样式设置(如设置高亮显示等)操作,SpannableString 类实现了 Spannable 接口,支持设置文本样式。
|
|
|
|
|
SpannableString spannable = new SpannableString(fullText == null ? "" : fullText);
|
|
|
|
|
if (!TextUtils.isEmpty(userQuery)) {
|
|
|
|
|
mPattern = Pattern.compile(userQuery);
|
|
|
|
|
// 创建一个 Matcher 对象,通过调用 Pattern 对象的 matcher 方法并传入完整文本(fullText),用于在文本中执行具体的匹配查找任务,
|
|
|
|
|
// 可以通过其方法判断是否找到匹配内容以及获取匹配的位置等信息。
|
|
|
|
|
Matcher m = mPattern.matcher(fullText);
|
|
|
|
|
int start = 0;
|
|
|
|
|
while (m.find(start)) {
|
|
|
|
@ -723,10 +873,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return spannable;
|
|
|
|
|
// 返回处理后的包含高亮显示效果的 SpannableString 对象,该对象可以用于在界面上展示带有高亮查询结果的文本内容。
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private View getListItem(String item, int index) {
|
|
|
|
|
// 通过LayoutInflater从当前Activity的上下文(this)加载一个布局资源(R.layout.note_edit_list_item)创建一个视图对象,
|
|
|
|
|
// 该布局资源定义了列表项的具体界面结构,包含文本编辑框、复选框等组件的布局样式。
|
|
|
|
|
View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null);
|
|
|
|
|
// 从创建的视图中获取文本编辑框(NoteEditText)组件,用于后续设置文本外观、内容以及添加事件监听器等操作。
|
|
|
|
|
final NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
|
|
|
|
|
edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
|
|
|
|
|
CheckBox cb = ((CheckBox) view.findViewById(R.id.cb_edit_item));
|
|
|
|
@ -735,11 +889,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
if (isChecked) {
|
|
|
|
|
edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
|
|
|
|
} else {
|
|
|
|
|
// 如果复选框未被选中,设置文本编辑框(edit)的绘制标志为默认的文本抗锯齿(Paint.ANTI_ALIAS_FLAG)和字距调整(Paint.DEV_KERN_TEXT_FLAG)标志,
|
|
|
|
|
// 恢复文本的正常显示样式
|
|
|
|
|
edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 判断列表项文本(item)是否以特定的标记(TAG_CHECKED)开头,如果是,表示该项初始状态为已选中状态。
|
|
|
|
|
if (item.startsWith(TAG_CHECKED)) {
|
|
|
|
|
cb.setChecked(true);
|
|
|
|
|
edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
|
|
|
@ -750,20 +907,31 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
item = item.substring(TAG_UNCHECKED.length(), item.length()).trim();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 为文本编辑框(edit)设置文本内容变化的监听器(OnTextViewChangeListener),这里传入当前Activity(this),可能在监听器中实现了相应的逻辑,
|
|
|
|
|
// 用于在文本编辑框内容改变时进行一些处理,比如实时更新相关数据等操作。
|
|
|
|
|
edit.setOnTextViewChangeListener(this);
|
|
|
|
|
edit.setIndex(index);
|
|
|
|
|
// 设置文本编辑框(edit)的文本内容,通过调用 getHighlightQueryResult 方法,根据当前列表项文本(item)和用户查询文本(mUserQuery)获取带有高亮显示效果的文本内容,
|
|
|
|
|
// 并设置到文本编辑框中展示给用户。
|
|
|
|
|
edit.setText(getHighlightQueryResult(item, mUserQuery));
|
|
|
|
|
return view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onTextChange(int index, boolean hasText) {
|
|
|
|
|
// 判断传入的索引(index)是否大于等于多行文本列表(mEditTextList)中的子项数量(即行数),如果大于等于则说明索引超出范围,
|
|
|
|
|
// 记录错误日志提示不应该出现这种情况,然后直接返回,不进行后续操作。
|
|
|
|
|
if (index >= mEditTextList.getChildCount()) {
|
|
|
|
|
Log.e(TAG, "Wrong index, should not happen");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 如果文本编辑框中有文本内容(hasText 为 true),则获取多行文本列表中对应索引位置的视图,并找到其中的复选框(CheckBox)组件,将其设置为可见状态,
|
|
|
|
|
// 以便用户可以看到并操作该复选框,通常用于有文本内容时可进行选中相关操作。
|
|
|
|
|
|
|
|
|
|
if(hasText) {
|
|
|
|
|
mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.VISIBLE);
|
|
|
|
|
} else {
|
|
|
|
|
// 如果文本编辑框中没有文本内容(hasText 为 false),则获取多行文本列表中对应索引位置的视图,并找到其中的复选框(CheckBox)组件,将其设置为不可见状态,
|
|
|
|
|
// 隐藏复选框,因为没有文本内容时可能不需要显示复选框进行相关操作。
|
|
|
|
|
mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -777,6 +945,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
""));
|
|
|
|
|
}
|
|
|
|
|
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
|
|
|
|
|
// 设置笔记编辑框(mNoteEditor)的文本内容,通过调用 getHighlightQueryResult 方法,根据正在编辑的笔记对象(mWorkingNote)的内容和用户查询文本(mUserQuery),
|
|
|
|
|
// 获取带有高亮显示效果的文本内容,并设置到笔记编辑框中展示给用户,恢复普通文本编辑模式下的文本显示。
|
|
|
|
|
mEditTextList.setVisibility(View.GONE);
|
|
|
|
|
mNoteEditor.setVisibility(View.VISIBLE);
|
|
|
|
|
}
|
|
|
|
@ -784,6 +954,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
|
|
|
|
|
private boolean getWorkingText() {
|
|
|
|
|
boolean hasChecked = false;
|
|
|
|
|
// 判断正在编辑的笔记对象(mWorkingNote)的复选框列表模式(通过 getCheckListMode 方法获取)是否为 TextNote.MODE_CHECK_LIST(即处于复选框列表模式)。
|
|
|
|
|
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
for (int i = 0; i < mEditTextList.getChildCount(); i++) {
|
|
|
|
@ -792,8 +963,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
if (!TextUtils.isEmpty(edit.getText())) {
|
|
|
|
|
if (((CheckBox) view.findViewById(R.id.cb_edit_item)).isChecked()) {
|
|
|
|
|
sb.append(TAG_CHECKED).append(" ").append(edit.getText()).append("\n");
|
|
|
|
|
// 如果复选框处于选中状态,将特定的选中标记(TAG_CHECKED)、空格以及文本编辑框中的文本内容拼接起来,并添加换行符,
|
|
|
|
|
// 按照特定格式构建列表项文本内容,添加到 StringBuilder 中,同时将 hasChecked 标记为 true,表示存在已选中的列表项。
|
|
|
|
|
hasChecked = true;
|
|
|
|
|
} else {
|
|
|
|
|
// 如果笔记对象不处于复选框列表模式,则直接将笔记编辑框(mNoteEditor)中的文本内容(通过调用其 getText 方法获取文本内容并转换为字符串),
|
|
|
|
|
// 设置为正在编辑的笔记对象(mWorkingNote)的工作文本内容,通过调用其 setWorkingText 方法实现。
|
|
|
|
|
sb.append(TAG_UNCHECKED).append(" ").append(edit.getText()).append("\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -818,6 +993,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
*/
|
|
|
|
|
setResult(RESULT_OK);
|
|
|
|
|
}
|
|
|
|
|
// 返回保存操作是否成功的布尔值,以便调用此方法的地方根据返回值进行相应的后续处理,比如提示用户保存成功与否等情况。
|
|
|
|
|
return saved;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -844,6 +1020,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
sender.putExtra("duplicate", true);
|
|
|
|
|
sender.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
|
|
|
|
|
showToast(R.string.info_note_enter_desktop);
|
|
|
|
|
// 此方法用于将正在编辑的笔记相关的快捷方式发送到桌面,在操作前会先确保笔记已保存(如果是新笔记则先调用saveNote方法保存),
|
|
|
|
|
// 然后根据笔记的ID是否有效(大于0表示有效)构建相应的Intent并发送广播来创建桌面快捷方式,若笔记ID无效则提示用户输入内容。
|
|
|
|
|
sendBroadcast(sender);
|
|
|
|
|
} else {
|
|
|
|
|
/**
|
|
|
|
@ -856,9 +1034,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 此方法用于处理正在编辑的笔记内容文本,去除其中特定的标记(如选中、未选中标记),并根据设定的最大长度限制(SHORTCUT_ICON_TITLE_MAX_LEN)对文本进行截断处理,
|
|
|
|
|
// 最终返回处理后的适合作为桌面快捷方式图标的标题文本。
|
|
|
|
|
private String makeShortcutIconTitle(String content) {
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
@ -867,6 +1049,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
showToast(resId, Toast.LENGTH_SHORT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 此重载方法用于根据传入的提示信息对应的资源ID(resId)以及显示时长参数(duration),创建并显示一个Toast提示信息,
|
|
|
|
|
// 通过调用Toast的makeText方法传入当前Activity的上下文(this)、提示信息资源ID以及显示时长,然后调用show方法将Toast显示出来,
|
|
|
|
|
// 用于在应用中向用户展示简短的提示信息,如操作成功、失败等提示内容。
|
|
|
|
|
private void showToast(int resId, int duration) {
|
|
|
|
|
Toast.makeText(this, resId, duration).show();
|
|
|
|
|
}
|
|
|
|
|