You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pyx_gitpractice/ui/NoteEditActivity.java

1330 lines
57 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.ui;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Paint;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.BackgroundColorSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.TextNote;
import net.micode.notes.model.WorkingNote;
import net.micode.notes.model.WorkingNote.NoteSettingChangedListener;
import net.micode.notes.tool.DataUtils;
import net.micode.notes.tool.ResourceParser;
import net.micode.notes.tool.ResourceParser.TextAppearanceResources;
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;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* NoteEditActivity 类用于处理笔记的编辑界面。
* 它继承自 Activity 类,实现了 OnClickListener、NoteSettingChangedListener 和 OnTextViewChangeListener 接口。
*/
public class NoteEditActivity extends Activity implements OnClickListener,
NoteSettingChangedListener, OnTextViewChangeListener {
/**
* 内部类 HeadViewHolder 用于存储笔记头部视图的引用。
*/
private class HeadViewHolder {
// 显示笔记修改日期的 TextView
public TextView tvModified;
// 提醒图标 ImageView
public ImageView ivAlertIcon;
// 显示提醒日期的 TextView
public TextView tvAlertDate;
// 设置背景颜色的按钮 ImageView
public ImageView ibSetBgColor;
}
// 背景选择按钮与背景颜色资源 ID 的映射
private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>();
static {
// 将黄色背景选择按钮 ID 与黄色背景资源 ID 关联
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
// 将红色背景选择按钮 ID 与红色背景资源 ID 关联
sBgSelectorBtnsMap.put(R.id.iv_bg_red, ResourceParser.RED);
// 将蓝色背景选择按钮 ID 与蓝色背景资源 ID 关联
sBgSelectorBtnsMap.put(R.id.iv_bg_blue, ResourceParser.BLUE);
// 将绿色背景选择按钮 ID 与绿色背景资源 ID 关联
sBgSelectorBtnsMap.put(R.id.iv_bg_green, ResourceParser.GREEN);
// 将白色背景选择按钮 ID 与白色背景资源 ID 关联
sBgSelectorBtnsMap.put(R.id.iv_bg_white, ResourceParser.WHITE);
}
// 背景颜色资源 ID 与选中状态图标 ID 的映射
private static final Map<Integer, Integer> sBgSelectorSelectionMap = new HashMap<Integer, Integer>();
static {
// 将黄色背景资源 ID 与黄色背景选中状态图标 ID 关联
sBgSelectorSelectionMap.put(ResourceParser.YELLOW, R.id.iv_bg_yellow_select);
// 将红色背景资源 ID 与红色背景选中状态图标 ID 关联
sBgSelectorSelectionMap.put(ResourceParser.RED, R.id.iv_bg_red_select);
// 将蓝色背景资源 ID 与蓝色背景选中状态图标 ID 关联
sBgSelectorSelectionMap.put(ResourceParser.BLUE, R.id.iv_bg_blue_select);
// 将绿色背景资源 ID 与绿色背景选中状态图标 ID 关联
sBgSelectorSelectionMap.put(ResourceParser.GREEN, R.id.iv_bg_green_select);
// 将白色背景资源 ID 与白色背景选中状态图标 ID 关联
sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select);
}
// 字体大小选择按钮与字体大小资源 ID 的映射
private static final Map<Integer, Integer> sFontSizeBtnsMap = new HashMap<Integer, Integer>();
static {
// 将大字体选择按钮 ID 与大字体资源 ID 关联
sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE);
// 将小字体选择按钮 ID 与小字体资源 ID 关联
sFontSizeBtnsMap.put(R.id.ll_font_small, ResourceParser.TEXT_SMALL);
// 将正常字体选择按钮 ID 与正常字体资源 ID 关联
sFontSizeBtnsMap.put(R.id.ll_font_normal, ResourceParser.TEXT_MEDIUM);
// 将超大字体选择按钮 ID 与超大字体资源 ID 关联
sFontSizeBtnsMap.put(R.id.ll_font_super, ResourceParser.TEXT_SUPER);
}
// 字体大小资源 ID 与选中状态图标 ID 的映射
private static final Map<Integer, Integer> sFontSelectorSelectionMap = new HashMap<Integer, Integer>();
static {
// 将大字体资源 ID 与大字体选中状态图标 ID 关联
sFontSelectorSelectionMap.put(ResourceParser.TEXT_LARGE, R.id.iv_large_select);
// 将小字体资源 ID 与小字体选中状态图标 ID 关联
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SMALL, R.id.iv_small_select);
// 将正常字体资源 ID 与正常字体选中状态图标 ID 关联
sFontSelectorSelectionMap.put(ResourceParser.TEXT_MEDIUM, R.id.iv_medium_select);
// 将超大字体资源 ID 与超大字体选中状态图标 ID 关联
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SUPER, R.id.iv_super_select);
}
// 日志标签
private static final String TAG = "NoteEditActivity";
// 笔记头部视图持有者
private HeadViewHolder mNoteHeaderHolder;
// 笔记头部视图面板
private View mHeadViewPanel;
// 笔记背景颜色选择器视图
private View mNoteBgColorSelector;
// 字体大小选择器视图
private View mFontSizeSelector;
// 笔记编辑器 EditText
private EditText mNoteEditor;
// 笔记编辑器面板视图
private View mNoteEditorPanel;
// 工作笔记对象
private WorkingNote mWorkingNote;
// 共享偏好设置对象
private SharedPreferences mSharedPrefs;
// 字体大小 ID
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;
// 正则表达式模式
private Pattern mPattern;
/**
* Activity 创建时调用的方法。
* 用于设置布局、初始化活动状态和资源。
*
* @param savedInstanceState 保存的实例状态
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置布局
this.setContentView(R.layout.note_edit);
// 如果 savedInstanceState 为空且初始化活动状态失败,则关闭活动
if (savedInstanceState == null && !initActivityState(getIntent())) {
finish();
return;
}
// 初始化资源
initResources();
}
/**
* 恢复 Activity 状态时调用的方法。
* 当 Activity 因内存不足被杀死后重新启动时,恢复之前的状态。
*
* @param savedInstanceState 保存的实例状态
*/
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// 如果 savedInstanceState 不为空且包含 Intent.EXTRA_UID
if (savedInstanceState != null && savedInstanceState.containsKey(Intent.EXTRA_UID)) {
// 创建一个新的 Intent 用于查看笔记
Intent intent = new Intent(Intent.ACTION_VIEW);
// 将保存的笔记 ID 放入 Intent 中
intent.putExtra(Intent.EXTRA_UID, savedInstanceState.getLong(Intent.EXTRA_UID));
// 初始化活动状态,如果失败则关闭活动
if (!initActivityState(intent)) {
finish();
return;
}
// 记录日志
Log.d(TAG, "Restoring from killed activity");
}
}
/**
* 初始化活动状态的方法。
* 根据传入的 Intent 初始化工作笔记对象。
*
* @param intent 传入的 Intent
* @return 初始化成功返回 true失败返回 false
*/
private boolean initActivityState(Intent intent) {
// 初始化工作笔记对象为 null
mWorkingNote = null;
// 如果 Intent 的动作是 ACTION_VIEW
if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) {
// 获取笔记 ID
long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0);
// 初始化用户查询字符串为空
mUserQuery = "";
// 如果 Intent 包含搜索结果相关信息
if (intent.hasExtra(SearchManager.EXTRA_DATA_KEY)) {
// 从搜索结果中获取笔记 ID
noteId = Long.parseLong(intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
// 获取用户查询字符串
mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY);
}
// 检查笔记是否在数据库中可见
if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) {
// 如果不可见,跳转到笔记列表活动
Intent jump = new Intent(this, NotesListActivity.class);
startActivity(jump);
// 显示提示信息
showToast(R.string.error_note_not_exist);
// 关闭当前活动
finish();
return false;
} else {
// 加载工作笔记对象
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())) {
// 如果 Intent 的动作是 ACTION_INSERT_OR_EDIT创建新笔记
// 获取文件夹 ID
long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0);
// 获取小部件 ID
int widgetId = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
// 获取小部件类型
int widgetType = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_TYPE,
Notes.TYPE_WIDGET_INVALIDE);
// 获取背景资源 ID
int bgResId = intent.getIntExtra(Notes.INTENT_EXTRA_BACKGROUND_ID,
ResourceParser.getDefaultBgId(this));
// 解析通话记录笔记
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
long callDate = intent.getLongExtra(Notes.INTENT_EXTRA_CALL_DATE, 0);
if (callDate != 0 && phoneNumber != null) {
if (TextUtils.isEmpty(phoneNumber)) {
// 如果电话号码为空,记录警告日志
Log.w(TAG, "The call record number is null");
}
long noteId = 0;
// 根据电话号码和通话日期查找笔记 ID
if ((noteId = DataUtils.getNoteIdByPhoneNumberAndCallDate(getContentResolver(),
phoneNumber, callDate)) > 0) {
// 加载通话记录笔记
mWorkingNote = WorkingNote.load(this, noteId);
if (mWorkingNote == null) {
// 如果加载失败,记录错误日志并关闭活动
Log.e(TAG, "load call note failed with note id" + noteId);
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);
} else {
// 如果 Intent 未指定有效动作,记录错误日志并关闭活动
Log.e(TAG, "Intent not specified action, should not support");
finish();
return false;
}
// 设置笔记设置状态改变监听器
mWorkingNote.setOnSettingStatusChangedListener(this);
return true;
}
/**
* Activity 恢复时调用的方法。
* 用于初始化笔记界面。
*/
@Override
protected void onResume() {
super.onResume();
// 初始化笔记界面
initNoteScreen();
}
/**
* 初始化笔记界面的方法。
* 设置笔记编辑器的文本样式、内容,背景颜色,修改日期和提醒信息。
*/
private void initNoteScreen() {
// 设置笔记编辑器的文本样式
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());
}
// 隐藏所有背景选择器的选中状态图标
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
| DateUtils.FORMAT_SHOW_YEAR));
/**
* 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();
// 检查当前时间是否超过了提醒时间
if (time > mWorkingNote.getAlertDate()) {
// 如果超过了提醒时间,显示提醒已过期的文本
mNoteHeaderHolder.tvAlertDate.setText(R.string.note_alert_expired);
} else {
// 如果未超过提醒时间显示相对提醒时间如“10分钟后”
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 时调用此方法。用于重新初始化活动状态。
*
* @param intent 接收到的新 Intent
*/
@Override
protected void onNewIntent(Intent intent) {
// 调用父类的 onNewIntent 方法
super.onNewIntent(intent);
// 初始化活动状态
initActivityState(intent);
}
/**
* 在 Activity 被销毁前保存实例状态的方法。如果笔记是新创建且未保存到数据库,先保存笔记,然后将笔记 ID 保存到 Bundle 中。
*
* @param outState 用于保存实例状态的 Bundle
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
// 调用父类的 onSaveInstanceState 方法
super.onSaveInstanceState(outState);
/**
* 对于没有笔记 ID 的新笔记,我们应该先保存它以生成一个 ID。如果正在编辑的笔记不值得保存
* 则没有 ID这相当于创建一个新笔记。
*/
if (!mWorkingNote.existInDatabase()) {
// 保存笔记
saveNote();
}
// 将工作笔记的 ID 放入 outState 中
outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId());
// 记录日志,显示保存的工作笔记 ID
Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState");
}
/**
* 分发触摸事件的方法。如果背景颜色选择器或字体大小选择器可见,且触摸事件不在其范围内,则隐藏选择器。
*
* @param ev 触摸事件
* @return 如果处理了触摸事件返回 true否则调用父类的 dispatchTouchEvent 方法
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// 检查背景颜色选择器是否可见且触摸事件不在其范围内
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);
}
/**
* 判断触摸事件是否在指定视图范围内的方法。
*
* @param view 要检查的视图
* @param ev 触摸事件
* @return 如果触摸事件在视图范围内返回 true否则返回 false
*/
private boolean inRangeOfView(View view, MotionEvent ev) {
// 用于存储视图在屏幕上的位置
int[] location = new int[2];
// 获取视图在屏幕上的位置
view.getLocationOnScreen(location);
// 获取视图的 X 坐标
int x = location[0];
// 获取视图的 Y 坐标
int y = location[1];
// 检查触摸事件的坐标是否在视图范围内
if (ev.getX() < x
|| ev.getX() > (x + view.getWidth())
|| ev.getY() < y
|| ev.getY() > (y + view.getHeight())) {
return false;
}
return true;
}
/**
* 初始化资源的方法。查找并初始化各种视图组件,设置点击监听器,读取共享偏好设置中的字体大小。
*/
private void initResources() {
// 查找笔记标题视图
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);
// 查找并初始化笔记编辑器
mNoteEditor = (EditText) findViewById(R.id.note_edit_view);
// 查找并初始化笔记编辑面板
mNoteEditorPanel = findViewById(R.id.sv_note_edit);
// 查找并初始化笔记背景颜色选择器
mNoteBgColorSelector = findViewById(R.id.note_bg_color_selector);
// 遍历背景颜色选择按钮的 ID
for (int id : sBgSelectorBtnsMap.keySet()) {
// 查找背景颜色选择按钮
ImageView iv = (ImageView) findViewById(id);
// 为背景颜色选择按钮设置点击监听器
iv.setOnClickListener(this);
}
// 查找并初始化字体大小选择器
mFontSizeSelector = findViewById(R.id.font_size_selector);
// 遍历字体大小选择按钮的 ID
for (int id : sFontSizeBtnsMap.keySet()) {
// 查找字体大小选择按钮
View view = findViewById(id);
// 为字体大小选择按钮设置点击监听器
view.setOnClickListener(this);
}
// 获取默认的共享偏好设置
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
// 从共享偏好设置中获取字体大小 ID如果不存在则使用默认值
mFontSizeId = mSharedPrefs.getInt(PREFERENCE_FONT_SIZE, ResourceParser.BG_DEFAULT_FONT_SIZE);
/**
* 修复在共享偏好设置中存储资源 ID 的 bug。如果 ID 大于资源数组的长度,
* 则返回默认的字体大小 ID。
*/
if (mFontSizeId >= TextAppearanceResources.getResourcesSize()) {
mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE;
}
// 查找并初始化编辑文本列表
mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
}
/**
* Activity 暂停时调用的方法。保存笔记数据,并清除设置状态。
*/
@Override
protected void onPause() {
// 调用父类的 onPause 方法
super.onPause();
// 保存笔记,如果保存成功则记录日志
if (saveNote()) {
Log.d(TAG, "Note data was saved with length:" + mWorkingNote.getContent().length());
}
// 清除设置状态
clearSettingState();
}
/**
* 更新小部件的方法。根据笔记的小部件类型,发送广播更新相应的小部件。
*/
private void updateWidget() {
// 创建一个用于更新小部件的 Intent
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
// 检查笔记的小部件类型是否为 2x
if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) {
// 设置 Intent 的目标类为 2x 小部件提供者
intent.setClass(this, NoteWidgetProvider_2x.class);
} else if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_4X) {
// 设置 Intent 的目标类为 4x 小部件提供者
intent.setClass(this, NoteWidgetProvider_4x.class);
} else {
// 如果是不支持的小部件类型,记录错误日志并返回
Log.e(TAG, "Unspported widget type");
return;
}
// 将笔记的小部件 ID 放入 Intent 中
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[]{
mWorkingNote.getWidgetId()
});
// 发送广播更新小部件
sendBroadcast(intent);
// 设置 Activity 的结果为成功
setResult(RESULT_OK, intent);
}
/**
* 处理视图点击事件的方法。根据点击的视图 ID执行相应的操作如显示背景颜色选择器、设置背景颜色、设置字体大小等。
*
* @param v 被点击的视图
*/
public void onClick(View v) {
// 获取被点击视图的 ID
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)) {
// 如果点击的是背景颜色选择按钮
// 隐藏当前选中的背景颜色的选中标记
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.GONE);
// 设置工作笔记的背景颜色 ID
mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));
// 隐藏背景颜色选择器
mNoteBgColorSelector.setVisibility(View.GONE);
} else if (sFontSizeBtnsMap.containsKey(id)) {
// 如果点击的是字体大小选择按钮
// 隐藏当前选中的字体大小的选中标记
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.GONE);
// 更新字体大小 ID
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));
}
// 隐藏字体大小选择器
mFontSizeSelector.setVisibility(View.GONE);
}
}
/**
* 处理返回按钮点击事件的方法。如果有设置状态(如背景颜色选择器或字体大小选择器可见),则清除状态;否则保存笔记并返回。
*/
@Override
public void onBackPressed() {
// 尝试清除设置状态,如果清除成功则返回
if (clearSettingState()) {
return;
}
// 保存笔记
saveNote();
// 调用父类的 onBackPressed 方法处理返回操作
super.onBackPressed();
}
/**
* 清除设置状态的方法。如果背景颜色选择器或字体大小选择器可见,则隐藏它们并返回 true否则返回 false。
*
* @return 如果清除了设置状态返回 true否则返回 false
*/
private boolean clearSettingState() {
// 检查背景颜色选择器是否可见
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE) {
// 隐藏背景颜色选择器
mNoteBgColorSelector.setVisibility(View.GONE);
return true;
} else if (mFontSizeSelector.getVisibility() == View.VISIBLE) {
// 检查字体大小选择器是否可见
// 隐藏字体大小选择器
mFontSizeSelector.setVisibility(View.GONE);
return true;
}
return false;
}
/**
* 当背景颜色改变时调用的方法。更新背景颜色选择器的选中标记,并更新笔记编辑器和头部视图的背景资源。
*/
public void onBackgroundColorChanged() {
// 显示当前选中的背景颜色的选中标记
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.VISIBLE);
// 设置笔记编辑器面板的背景资源
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
// 设置笔记头部视图面板的背景资源
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
}
/**
* 准备选项菜单的方法。在菜单显示之前,清除设置状态,根据笔记的文件夹 ID 加载不同的菜单布局,
* 并根据笔记的检查列表模式和提醒状态设置菜单项的标题和可见性。
*
* @param menu 要准备的菜单
* @return 如果 Activity 正在结束返回 true否则返回父类的 onPrepareOptionsMenu 方法的结果
*/
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// 检查 Activity 是否正在结束
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 {
// 如果未设置提醒,隐藏删除提醒菜单项
menu.findItem(R.id.menu_delete_remind).setVisible(false);
}
return true;
}
@Override
/**
* 处理选项菜单中菜单项的点击事件
*
* @param item 被点击的菜单项
* @return 如果事件已处理则返回 true
*/
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_new_note:
// 点击新建笔记菜单项,调用创建新笔记的方法
createNewNote();
break;
case 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() {
public void onClick(DialogInterface dialog, int which) {
// 点击确认按钮,删除当前笔记并关闭当前活动
deleteCurrentNote();
finish();
}
});
// 设置取消按钮,点击后不做任何操作
builder.setNegativeButton(android.R.string.cancel, null);
// 显示对话框
builder.show();
break;
case R.id.menu_font_size:
// 点击字体大小菜单项,显示字体大小选择器
mFontSizeSelector.setVisibility(View.VISIBLE);
// 显示当前选中字体大小的指示器
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);
break;
case R.id.menu_list_mode:
// 点击列表模式菜单项,切换笔记的列表模式
mWorkingNote.setCheckListMode(mWorkingNote.getCheckListMode() == 0 ?
TextNote.MODE_CHECK_LIST : 0);
break;
case R.id.menu_share:
// 点击分享菜单项,获取当前笔记内容并分享
getWorkingText();
sendTo(this, mWorkingNote.getContent());
break;
case R.id.menu_send_to_desktop:
// 点击发送到桌面菜单项,将笔记创建快捷方式到桌面
sendToDesktop();
break;
case R.id.menu_alert:
// 点击设置提醒菜单项,弹出日期时间选择对话框设置提醒
setReminder();
break;
case R.id.menu_delete_remind:
// 点击删除提醒菜单项,取消当前笔记的提醒设置
mWorkingNote.setAlertDate(0, false);
break;
default:
break;
}
return true;
}
/**
* 设置提醒的方法,弹出日期时间选择对话框
*/
private void setReminder() {
// 创建日期时间选择对话框,初始时间为当前时间
DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis());
// 设置日期时间选择监听器
d.setOnDateTimeSetListener(new OnDateTimeSetListener() {
public void OnDateTimeSet(AlertDialog dialog, long date) {
// 用户选择日期时间后,设置笔记的提醒日期
mWorkingNote.setAlertDate(date, true);
}
});
// 显示日期时间选择对话框
d.show();
}
/**
* 将笔记内容分享到支持文本分享的应用
*
* @param context 上下文对象
* @param info 要分享的笔记内容
*/
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);
}
/**
* 创建新笔记的方法
*/
private void createNewNote() {
// 首先保存当前正在编辑的笔记
saveNote();
// 为了安全起见,关闭当前活动
finish();
// 创建一个新的笔记编辑活动意图
Intent intent = new Intent(this, NoteEditActivity.class);
// 设置意图动作为插入或编辑
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
// 传递当前笔记所在文件夹的 ID
intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mWorkingNote.getFolderId());
// 启动新的笔记编辑活动
startActivity(intent);
}
/**
* 删除当前笔记的方法
*/
private void deleteCurrentNote() {
if (mWorkingNote.existInDatabase()) {
// 创建一个存储笔记 ID 的集合
HashSet<Long> ids = new HashSet<Long>();
// 获取当前笔记的 ID
long id = mWorkingNote.getNoteId();
if (id != Notes.ID_ROOT_FOLDER) {
// 如果笔记 ID 不是根文件夹 ID则将其添加到集合中
ids.add(id);
} else {
// 记录错误日志,这种情况不应该发生
Log.d(TAG, "Wrong note id, should not happen");
}
if (!isSyncMode()) {
// 如果不是同步模式,直接批量删除笔记
if (!DataUtils.batchDeleteNotes(getContentResolver(), ids)) {
// 记录删除笔记错误日志
Log.e(TAG, "Delete Note error");
}
} 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);
}
/**
* 判断是否处于同步模式
*
* @return 如果有同步账户则返回 true否则返回 false
*/
private boolean isSyncMode() {
return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
}
/**
* 当笔记的提醒时钟设置发生变化时调用的方法
*
* @param date 提醒日期
* @param set 是否设置提醒
*/
public void onClockAlertChanged(long date, boolean set) {
/**
* 用户可能会对未保存的笔记设置时钟提醒,因此在设置提醒时钟之前,我们应该先保存笔记
*/
if (!mWorkingNote.existInDatabase()) {
saveNote();
}
if (mWorkingNote.getNoteId() > 0) {
// 创建一个广播意图,用于触发提醒
Intent intent = new Intent(this, AlarmReceiver.class);
// 设置意图的数据为笔记的 URI
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);
}
} else {
/**
* 存在用户未输入任何内容(笔记不值得保存)的情况,此时没有笔记 ID提醒用户应该输入一些内容
*/
Log.e(TAG, "Clock alert setting error");
showToast(R.string.error_note_empty_for_clock);
}
}
/**
* 当笔记的小部件设置发生变化时调用的方法
*/
public void onWidgetChanged() {
// 更新小部件
updateWidget();
}
/**
* 当编辑文本被删除时调用的方法
*
* @param index 被删除文本的索引
* @param text 被删除的文本内容
*/
public void onEditTextDelete(int index, String text) {
// 获取编辑文本列表的子视图数量
int childCount = mEditTextList.getChildCount();
if (childCount == 1) {
// 如果只有一个子视图,则不做处理
return;
}
// 更新后续编辑文本的索引
for (int i = index + 1; i < childCount; i++) {
((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text))
.setIndex(i - 1);
}
// 移除指定索引的编辑文本视图
mEditTextList.removeViewAt(index);
NoteEditText edit = null;
if (index == 0) {
// 如果删除的是第一个视图,获取第一个编辑文本视图
edit = (NoteEditText) mEditTextList.getChildAt(0).findViewById(
R.id.et_edit_text);
} else {
// 否则获取前一个编辑文本视图
edit = (NoteEditText) mEditTextList.getChildAt(index - 1).findViewById(
R.id.et_edit_text);
}
// 获取编辑文本的长度
int length = edit.length();
// 将被删除的文本追加到编辑文本中
edit.append(text);
// 请求焦点
edit.requestFocus();
// 设置光标位置
edit.setSelection(length);
}
/**
* 当在编辑文本中按下回车键时调用的方法
*
* @param index 按下回车键的编辑文本的索引
* @param text 当前编辑文本的内容
*/
public void onEditTextEnter(int index, String text) {
/**
* 这种情况不应该发生,用于调试检查
*/
if (index > mEditTextList.getChildCount()) {
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.setSelection(0);
// 更新后续编辑文本的索引
for (int i = index + 1; i < mEditTextList.getChildCount(); i++) {
((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text))
.setIndex(i);
}
}
/**
* 切换到列表模式的方法
*
* @param text 笔记内容
*/
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));
index++;
}
}
// 添加一个空的列表项
mEditTextList.addView(getListItem("", index));
// 让最后一个列表项的编辑文本获取焦点
mEditTextList.getChildAt(index).findViewById(R.id.et_edit_text).requestFocus();
// 隐藏普通编辑文本视图
mNoteEditor.setVisibility(View.GONE);
// 显示编辑文本列表视图
mEditTextList.setVisibility(View.VISIBLE);
}
/**
* 获取高亮显示查询结果的方法
*
* @param fullText 完整的笔记内容
* @param userQuery 用户的查询关键字
* @return 高亮显示查询结果的 Spannable 对象
*/
private Spannable getHighlightQueryResult(String fullText, String userQuery) {
// 创建一个 SpannableString 对象,用于存储完整的笔记内容
SpannableString spannable = new SpannableString(fullText == null ? "" : fullText);
if (!TextUtils.isEmpty(userQuery)) {
// 如果用户查询关键字不为空,编译正则表达式
mPattern = Pattern.compile(userQuery);
// 创建匹配器
Matcher m = mPattern.matcher(fullText);
int start = 0;
while (m.find(start)) {
// 找到匹配的关键字,设置背景颜色高亮显示
spannable.setSpan(
new BackgroundColorSpan(this.getResources().getColor(
R.color.user_query_highlight)), m.start(), m.end(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
start = m.end();
}
}
return spannable;
}
/**
* 获取列表项视图的方法
*
* @param item 列表项的内容
* @param index 列表项的索引
* @return 列表项视图
*/
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));
// 获取列表项中的复选框视图
CheckBox cb = ((CheckBox) view.findViewById(R.id.cb_edit_item));
// 设置复选框的选中状态改变监听器
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
// 如果复选框被选中,设置编辑文本的字体样式为删除线
edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
} else {
// 如果复选框未被选中,设置编辑文本的字体样式为正常
edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
}
}
});
if (item.startsWith(TAG_CHECKED)) {
// 如果列表项内容以选中标记开头,设置复选框为选中状态,并设置编辑文本的字体样式为删除线
cb.setChecked(true);
edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
// 去除选中标记,获取实际内容
item = item.substring(TAG_CHECKED.length(), item.length()).trim();
} else if (item.startsWith(TAG_UNCHECKED)) {
// 如果列表项内容以未选中标记开头,设置复选框为未选中状态,并设置编辑文本的字体样式为正常
cb.setChecked(false);
edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
// 去除未选中标记,获取实际内容
item = item.substring(TAG_UNCHECKED.length(), item.length()).trim();
}
// 设置编辑文本的文本变化监听器
edit.setOnTextViewChangeListener(this);
// 设置编辑文本的索引
edit.setIndex(index);
// 设置编辑文本的内容,并高亮显示查询结果
edit.setText(getHighlightQueryResult(item, mUserQuery));
return view;
}
/**
* 当编辑文本内容发生变化时调用的方法
*
* @param index 编辑文本的索引
* @param hasText 编辑文本是否有内容
*/
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);
}
}
/**
* 当笔记的列表模式发生变化时调用的方法
*
* @param oldMode 旧的列表模式
* @param newMode 新的列表模式
*/
public void onCheckListModeChanged(int oldMode, int newMode) {
// 如果新的模式是待办列表模式
if (newMode == TextNote.MODE_CHECK_LIST) {
// 将当前笔记编辑器中的文本转换为待办列表模式显示
switchToListMode(mNoteEditor.getText().toString());
} else {
// 如果获取工作文本失败
if (!getWorkingText()) {
// 去除工作文本中的未选中标记
mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ", ""));
}
// 设置笔记编辑器的文本,并高亮显示查询结果
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
// 隐藏待办列表视图
mEditTextList.setVisibility(View.GONE);
// 显示笔记编辑器视图
mNoteEditor.setVisibility(View.VISIBLE);
}
}
/**
* 获取当前工作文本,根据待办列表模式的不同进行处理
* @return 如果存在已选中的待办事项则返回 true否则返回 false
*/
private boolean getWorkingText() {
boolean hasChecked = false;
// 如果当前处于待办列表模式
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
// 创建一个 StringBuilder 用于拼接待办事项
StringBuilder sb = new StringBuilder();
// 遍历待办列表中的每个子视图
for (int i = 0; i < mEditTextList.getChildCount(); i++) {
// 获取当前子视图
View view = mEditTextList.getChildAt(i);
// 获取子视图中的编辑文本框
NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
// 如果编辑文本框中的文本不为空
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");
hasChecked = true;
} else {
// 如果复选框未被选中,添加未选中标记并拼接文本
sb.append(TAG_UNCHECKED).append(" ").append(edit.getText()).append("\n");
}
}
}
// 将拼接好的文本设置为工作文本
mWorkingNote.setWorkingText(sb.toString());
} else {
// 如果不是待办列表模式,直接将笔记编辑器中的文本设置为工作文本
mWorkingNote.setWorkingText(mNoteEditor.getText().toString());
}
return hasChecked;
}
/**
* 保存当前笔记
* @return 如果保存成功则返回 true否则返回 false
*/
private boolean saveNote() {
// 获取当前工作文本
getWorkingText();
// 调用 WorkingNote 的 saveNote 方法保存笔记
boolean saved = mWorkingNote.saveNote();
if (saved) {
/**
* 从列表视图进入编辑视图有两种模式:打开一个笔记,创建/编辑一个笔记。
* 打开笔记需要在从编辑视图返回时回到列表中的原始位置,而创建新笔记需要回到列表顶部。
* 此代码 RESULT_OK 用于标识创建/编辑状态
*/
setResult(RESULT_OK);
}
return saved;
}
/**
* 将当前笔记发送到桌面,创建快捷方式
*/
private void sendToDesktop() {
/**
* 在向主屏幕发送消息之前,需要确保当前编辑的笔记已经存在于数据库中。
* 因此,对于新笔记,首先保存它
*/
if (!mWorkingNote.existInDatabase()) {
saveNote();
}
// 如果笔记 ID 大于 0说明笔记已成功保存
if (mWorkingNote.getNoteId() > 0) {
// 创建一个意图用于发送快捷方式信息
Intent sender = new Intent();
// 创建一个快捷方式意图,用于打开当前笔记的编辑界面
Intent shortcutIntent = new Intent(this, NoteEditActivity.class);
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()));
// 设置快捷方式的图标资源
sender.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(this, R.drawable.icon_app));
// 允许创建重复的快捷方式
sender.putExtra("duplicate", true);
// 设置发送意图的动作,用于安装快捷方式
sender.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
// 显示提示信息,告知用户笔记已发送到桌面
showToast(R.string.info_note_enter_desktop);
// 发送广播,安装快捷方式
sendBroadcast(sender);
} else {
/**
* 存在用户未输入任何内容的情况(笔记不值得保存),此时没有笔记 ID
* 提醒用户应该输入一些内容
*/
Log.e(TAG, "Send to desktop error");
showToast(R.string.error_note_empty_for_send_to_desktop);
}
}
/**
* 生成快捷方式图标的标题,去除标记并截取长度
* @param content 笔记内容
* @return 生成的快捷方式图标标题
*/
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;
}
/**
* 显示短时间的 Toast 提示信息
* @param resId 提示信息的资源 ID
*/
private void showToast(int resId) {
showToast(resId, Toast.LENGTH_SHORT);
}
/**
* 显示指定时长的 Toast 提示信息
* @param resId 提示信息的资源 ID
* @param duration Toast 显示的时长
*/
private void showToast(int resId, int duration) {
Toast.makeText(this, resId, duration).show();
}
}