|
|
|
@ -71,7 +71,7 @@ import java.util.Map;
|
|
|
|
|
import java.util.regex.Matcher;
|
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//便签编辑有关的活动,实现了 OnClickListener(处理点击事件)、NoteSettingChangedListener(监测便签设置的变动) 和 OnTextViewChangeListener(监测便签编辑的变动) 接口,
|
|
|
|
|
public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
NoteSettingChangedListener, OnTextViewChangeListener {
|
|
|
|
|
private class HeadViewHolder {
|
|
|
|
@ -132,7 +132,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
|
|
|
|
|
private View mNoteEditorPanel;
|
|
|
|
|
|
|
|
|
|
private WorkingNote mWorkingNote;
|
|
|
|
|
private WorkingNote mWorkingNote; //记录当前正在工作的便签
|
|
|
|
|
|
|
|
|
|
private SharedPreferences mSharedPrefs;
|
|
|
|
|
private int mFontSizeId;
|
|
|
|
@ -165,18 +165,13 @@ 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)) {
|
|
|
|
|
// 构建一个带有 ACTION_VIEW 的 Intent,并传递之前保存的笔记id
|
|
|
|
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
|
|
|
|
intent.putExtra(Intent.EXTRA_UID, savedInstanceState.getLong(Intent.EXTRA_UID));
|
|
|
|
|
// 初始化Activity的工作状态
|
|
|
|
|
if (!initActivityState(intent)) {
|
|
|
|
|
// 如果初始化失败,则结束当前Activity
|
|
|
|
|
finish();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -184,29 +179,32 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//依据intent参数传递的Action采取动作
|
|
|
|
|
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())) {
|
|
|
|
|
// 如果用户指定了ACTION_VIEW但没有提供id,则跳转到NotesListActivity
|
|
|
|
|
long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0);
|
|
|
|
|
mUserQuery = "";
|
|
|
|
|
|
|
|
|
|
// 从搜索结果开始
|
|
|
|
|
/**
|
|
|
|
|
* Starting from the searched result
|
|
|
|
|
*/
|
|
|
|
|
if (intent.hasExtra(SearchManager.EXTRA_DATA_KEY)) {
|
|
|
|
|
noteId = Long.parseLong(intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
|
|
|
|
|
mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) {
|
|
|
|
|
// 如果数据库中不存在指定的笔记,则跳转到NotesListActivity并显示错误信息
|
|
|
|
|
Intent jump = new Intent(this, NotesListActivity.class);
|
|
|
|
|
startActivity(jump);
|
|
|
|
|
showToast(R.string.error_note_not_exist);
|
|
|
|
|
finish();
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
// 加载指定id的笔记
|
|
|
|
|
mWorkingNote = WorkingNote.load(this, noteId);
|
|
|
|
|
if (mWorkingNote == null) {
|
|
|
|
|
Log.e(TAG, "load note failed with note id" + noteId);
|
|
|
|
@ -218,7 +216,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
|
|
|
|
|
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
|
|
|
|
} else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) {
|
|
|
|
|
// 新建笔记
|
|
|
|
|
// New note
|
|
|
|
|
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 +225,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
int bgResId = intent.getIntExtra(Notes.INTENT_EXTRA_BACKGROUND_ID,
|
|
|
|
|
ResourceParser.getDefaultBgId(this));
|
|
|
|
|
|
|
|
|
|
// 解析来电记录笔记
|
|
|
|
|
// 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) {
|
|
|
|
@ -237,7 +235,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
long noteId = 0;
|
|
|
|
|
if ((noteId = DataUtils.getNoteIdByPhoneNumberAndCallDate(getContentResolver(),
|
|
|
|
|
phoneNumber, callDate)) > 0) {
|
|
|
|
|
// 加载指定id的来电记录笔记
|
|
|
|
|
mWorkingNote = WorkingNote.load(this, noteId);
|
|
|
|
|
if (mWorkingNote == null) {
|
|
|
|
|
Log.e(TAG, "load call note failed with note id" + noteId);
|
|
|
|
@ -245,13 +242,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 创建空的来电记录笔记并转换为来电记录
|
|
|
|
|
mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId,
|
|
|
|
|
widgetType, bgResId);
|
|
|
|
|
mWorkingNote.convertToCallNote(phoneNumber, callDate);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 创建空的笔记
|
|
|
|
|
mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId, widgetType,
|
|
|
|
|
bgResId);
|
|
|
|
|
}
|
|
|
|
@ -260,12 +255,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
|
|
|
|
|
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
|
|
|
|
} else {
|
|
|
|
|
// 如果Intent没有指定操作,则不应该支持该Intent,记录错误并关闭当前Activity
|
|
|
|
|
Log.e(TAG, "Intent not specified action, should not support");
|
|
|
|
|
finish();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 设置工作状态改变监听器并返回true表示初始化成功
|
|
|
|
|
mWorkingNote.setOnSettingStatusChangedListener(this);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -273,35 +266,24 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
@Override
|
|
|
|
|
protected void onResume() {
|
|
|
|
|
super.onResume();
|
|
|
|
|
initNoteScreen(); // 初始化笔记界面
|
|
|
|
|
initNoteScreen();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void initNoteScreen() {
|
|
|
|
|
// 设置笔记编辑器的文本外观
|
|
|
|
|
mNoteEditor.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
|
|
|
|
|
|
|
|
|
|
// 根据工作笔记的模式进行不同的处理
|
|
|
|
|
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
|
|
|
|
@ -311,33 +293,26 @@ private void initNoteScreen() {
|
|
|
|
|
* TODO: Add the menu for setting alert. Currently disable it because the DateTimePicker
|
|
|
|
|
* is not ready
|
|
|
|
|
*/
|
|
|
|
|
showAlertHeader(); // 显示提醒信息(如果有)
|
|
|
|
|
showAlertHeader();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void showAlertHeader() {
|
|
|
|
|
// 如果工作笔记设置了提醒
|
|
|
|
|
if (mWorkingNote.hasClockAlert()) {
|
|
|
|
|
long time = System.currentTimeMillis();
|
|
|
|
|
if (time > mWorkingNote.getAlertDate()) {
|
|
|
|
|
// 如果提醒时间已过期,显示"提醒已过期"
|
|
|
|
|
mNoteHeaderHolder.tvAlertDate.setText(R.string.note_alert_expired);
|
|
|
|
|
} else {
|
|
|
|
|
// 否则,显示距提醒时间的相对时间
|
|
|
|
|
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);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onNewIntent(Intent intent) {
|
|
|
|
|
super.onNewIntent(intent);
|
|
|
|
@ -347,224 +322,152 @@ protected void onNewIntent(Intent intent) {
|
|
|
|
|
@Override
|
|
|
|
|
protected void onSaveInstanceState(Bundle outState) {
|
|
|
|
|
super.onSaveInstanceState(outState);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 如果编辑的笔记尚未在数据库中存在(没有ID),我们先保存它以生成一个ID。
|
|
|
|
|
* 如果正在编辑的笔记不值得保存,则没有ID等同于创建新的笔记。
|
|
|
|
|
* For new note without note id, we should firstly save it to
|
|
|
|
|
* generate a id. If the editing note is not worth saving, there
|
|
|
|
|
* is no id which is equivalent to create new note
|
|
|
|
|
*/
|
|
|
|
|
if (!mWorkingNote.existInDatabase()) {
|
|
|
|
|
saveNote();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId());
|
|
|
|
|
Log.d(TAG, "保存正在编辑的笔记ID:" + mWorkingNote.getNoteId() + ",onSaveInstanceState");
|
|
|
|
|
Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean dispatchTouchEvent(MotionEvent ev) {
|
|
|
|
|
// 如果笔记背景颜色选择器可见,并且触摸事件的位置不在选择器内,隐藏选择器并返回true
|
|
|
|
|
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE
|
|
|
|
|
&& !inRangeOfView(mNoteBgColorSelector, ev)) {
|
|
|
|
|
mNoteBgColorSelector.setVisibility(View.GONE);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果字体大小选择器可见,并且触摸事件的位置不在选择器内,隐藏选择器并返回true
|
|
|
|
|
if (mFontSizeSelector.getVisibility() == View.VISIBLE
|
|
|
|
|
&& !inRangeOfView(mFontSizeSelector, ev)) {
|
|
|
|
|
mFontSizeSelector.setVisibility(View.GONE);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果触摸事件位置没有被处理,则调用父类的dispatchTouchEvent方法处理事件
|
|
|
|
|
return super.dispatchTouchEvent(ev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检查触摸事件的位置是否在给定View内部
|
|
|
|
|
*
|
|
|
|
|
* @param view 要检查的View
|
|
|
|
|
* @param ev 触摸事件
|
|
|
|
|
* @return 触摸事件位置是否在View内部
|
|
|
|
|
*/
|
|
|
|
|
private boolean inRangeOfView(View view, MotionEvent ev) {
|
|
|
|
|
int []location = new int[2];
|
|
|
|
|
view.getLocationOnScreen(location);
|
|
|
|
|
int x = location[0];
|
|
|
|
|
int y = location[1];
|
|
|
|
|
|
|
|
|
|
// 如果触摸事件的位置超出了View的边界,则返回false
|
|
|
|
|
if (ev.getX() < x
|
|
|
|
|
|| ev.getX() > (x + view.getWidth())
|
|
|
|
|
|| ev.getY() < y
|
|
|
|
|
|| ev.getY() > (y + view.getHeight())) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void initResources() {
|
|
|
|
|
// 初始化控件和资源
|
|
|
|
|
|
|
|
|
|
// 获取布局中的note_title并赋值给mHeadViewPanel
|
|
|
|
|
mHeadViewPanel = findViewById(R.id.note_title);
|
|
|
|
|
|
|
|
|
|
// 创建HeadViewHolder实例
|
|
|
|
|
mNoteHeaderHolder = new HeadViewHolder();
|
|
|
|
|
// 获取布局中的tv_modified_date并赋值给mNoteHeaderHolder中的tvModified
|
|
|
|
|
mNoteHeaderHolder.tvModified = (TextView) findViewById(R.id.tv_modified_date);
|
|
|
|
|
// 获取布局中的iv_alert_icon并赋值给mNoteHeaderHolder中的ivAlertIcon
|
|
|
|
|
mNoteHeaderHolder.ivAlertIcon = (ImageView) findViewById(R.id.iv_alert_icon);
|
|
|
|
|
// 获取布局中的tv_alert_date并赋值给mNoteHeaderHolder中的tvAlertDate
|
|
|
|
|
mNoteHeaderHolder.tvAlertDate = (TextView) findViewById(R.id.tv_alert_date);
|
|
|
|
|
// 获取布局中的btn_set_bg_color并赋值给mNoteHeaderHolder中的ibSetBgColor
|
|
|
|
|
mNoteHeaderHolder.ibSetBgColor = (ImageView) findViewById(R.id.btn_set_bg_color);
|
|
|
|
|
// 设置ibSetBgColor的点击事件监听器为当前Activity(this)
|
|
|
|
|
mNoteHeaderHolder.ibSetBgColor.setOnClickListener(this);
|
|
|
|
|
|
|
|
|
|
// 获取布局中的note_edit_view并赋值给mNoteEditor
|
|
|
|
|
mNoteEditor = (EditText) findViewById(R.id.note_edit_view);
|
|
|
|
|
// 获取布局中的sv_note_edit并赋值给mNoteEditorPanel
|
|
|
|
|
mNoteEditorPanel = findViewById(R.id.sv_note_edit);
|
|
|
|
|
|
|
|
|
|
// 获取布局中的note_bg_color_selector并赋值给mNoteBgColorSelector
|
|
|
|
|
mNoteBgColorSelector = findViewById(R.id.note_bg_color_selector);
|
|
|
|
|
// 遍历sBgSelectorBtnsMap中的按钮ID,并为每个按钮设置点击事件监听器为当前Activity(this)
|
|
|
|
|
for (int id : sBgSelectorBtnsMap.keySet()) {
|
|
|
|
|
ImageView iv = (ImageView) findViewById(id);
|
|
|
|
|
iv.setOnClickListener(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取布局中的font_size_selector并赋值给mFontSizeSelector
|
|
|
|
|
mFontSizeSelector = findViewById(R.id.font_size_selector);
|
|
|
|
|
// 遍历sFontSizeBtnsMap中的按钮ID,并为每个按钮设置点击事件监听器为当前Activity(this)
|
|
|
|
|
for (int id : sFontSizeBtnsMap.keySet()) {
|
|
|
|
|
View view = findViewById(id);
|
|
|
|
|
view.setOnClickListener(this);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取默认的SharedPreferences实例
|
|
|
|
|
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
|
|
|
|
// 从SharedPreferences中获取设置的字体大小ID,默认值为ResourceParser.BG_DEFAULT_FONT_SIZE
|
|
|
|
|
mFontSizeId = mSharedPrefs.getInt(PREFERENCE_FONT_SIZE, ResourceParser.BG_DEFAULT_FONT_SIZE);
|
|
|
|
|
/**
|
|
|
|
|
* HACKME: 修复存储资源ID的共享偏好的bug。
|
|
|
|
|
* ID可能大于资源的长度,在这种情况下,
|
|
|
|
|
* 将其设置为ResourceParser.BG_DEFAULT_FONT_SIZE。
|
|
|
|
|
* 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}
|
|
|
|
|
*/
|
|
|
|
|
if(mFontSizeId >= TextAppearanceResources.getResourcesSize()) {
|
|
|
|
|
mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取布局中的note_edit_list并赋值给mEditTextList
|
|
|
|
|
mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onPause() {
|
|
|
|
|
super.onPause();
|
|
|
|
|
// 当Activity暂停时,保存笔记数据并输出日志
|
|
|
|
|
if(saveNote()) {
|
|
|
|
|
Log.d(TAG, "Note data was saved with length:" + mWorkingNote.getContent().length());
|
|
|
|
|
}
|
|
|
|
|
// 清除设置状态
|
|
|
|
|
clearSettingState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateWidget() {
|
|
|
|
|
// 更新小部件
|
|
|
|
|
|
|
|
|
|
// 创建一个更新小部件的意图
|
|
|
|
|
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
|
|
|
|
|
|
|
|
|
|
// 根据工作笔记的小部件类型设置相应的小部件提供者类
|
|
|
|
|
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 {
|
|
|
|
|
// 不支持的小部件类型,输出错误日志并返回
|
|
|
|
|
Log.e(TAG, "Unspported widget type");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 将工作笔记的小部件ID作为额外数据放入意图中
|
|
|
|
|
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
|
|
|
|
|
mWorkingNote.getWidgetId()
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 发送广播来更新小部件
|
|
|
|
|
sendBroadcast(intent);
|
|
|
|
|
setResult(RESULT_OK, intent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
|
|
|
|
|
- View.VISIBLE);
|
|
|
|
|
} else if (sBgSelectorBtnsMap.containsKey(id)) {
|
|
|
|
|
// 如果点击的是背景颜色选择器中的一个按钮
|
|
|
|
|
// 隐藏当前工作笔记背景颜色的选择项
|
|
|
|
|
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(View.GONE);
|
|
|
|
|
// 设置新的背景颜色ID给工作笔记
|
|
|
|
|
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
|
|
|
|
|
View.GONE);
|
|
|
|
|
mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));
|
|
|
|
|
// 隐藏背景颜色选择器
|
|
|
|
|
mNoteBgColorSelector.setVisibility(View.GONE);
|
|
|
|
|
} else if (sFontSizeBtnsMap.containsKey(id)) {
|
|
|
|
|
// 如果点击的是字体大小选择器中的一个按钮
|
|
|
|
|
// 隐藏当前字体大小的选择项
|
|
|
|
|
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.GONE);
|
|
|
|
|
// 设置新的字体大小ID
|
|
|
|
|
mFontSizeId = sFontSizeBtnsMap.get(id);
|
|
|
|
|
// 将新的字体大小ID保存到SharedPreferences中
|
|
|
|
|
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));
|
|
|
|
|
mNoteEditor.setTextAppearance(this,
|
|
|
|
|
TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
|
|
|
|
|
}
|
|
|
|
|
// 隐藏字体大小选择器
|
|
|
|
|
mFontSizeSelector.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onBackPressed() {
|
|
|
|
|
// 当返回按钮按下时
|
|
|
|
|
if(clearSettingState()) {
|
|
|
|
|
// 如果当前状态是设置状态,清除设置状态并返回
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 保存工作笔记
|
|
|
|
|
saveNote();
|
|
|
|
|
super.onBackPressed();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
@ -572,116 +475,76 @@ private boolean clearSettingState() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onBackgroundColorChanged() {
|
|
|
|
|
// 根据当前工作笔记的背景颜色ID显示相应的选择项
|
|
|
|
|
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(View.VISIBLE);
|
|
|
|
|
// 设置工作笔记编辑面板的背景颜色为当前工作笔记的背景颜色资源ID
|
|
|
|
|
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
|
|
|
|
|
View.VISIBLE);
|
|
|
|
|
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
|
|
|
|
|
// 设置工作笔记标题栏的背景颜色为当前工作笔记的标题背景资源ID
|
|
|
|
|
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
|
|
|
|
// 菜单准备方法,动态显示菜单项
|
|
|
|
|
if (isFinishing()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
// 清除设置状态
|
|
|
|
|
clearSettingState();
|
|
|
|
|
// 清空菜单项
|
|
|
|
|
menu.clear();
|
|
|
|
|
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
|
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
|
int itemId = item.getItemId();
|
|
|
|
|
if (itemId == R.id.menu_new_note) {
|
|
|
|
|
// 当点击菜单项“新建笔记”时
|
|
|
|
|
createNewNote();
|
|
|
|
|
} else if (itemId == R.id.menu_delete) {
|
|
|
|
|
// 当点击菜单项“删除笔记”时
|
|
|
|
|
// 弹出确认对话框
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
|
|
|
createNewNote(); //新建便签
|
|
|
|
|
} else if (itemId == R.id.menu_delete) { //删除便签
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this); //创建一个 AlertDialog.Builder 对象,用于构建对话框
|
|
|
|
|
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,
|
|
|
|
|
builder.setPositiveButton(android.R.string.ok, //点击ok则删除该便签
|
|
|
|
|
new DialogInterface.OnClickListener() {
|
|
|
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
|
|
|
// 确认删除工作笔记,删除并结束当前活动
|
|
|
|
|
deleteCurrentNote();
|
|
|
|
|
finish();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
builder.setNegativeButton(android.R.string.cancel, null);
|
|
|
|
|
builder.show();
|
|
|
|
|
} else if (itemId == R.id.menu_font_size) {
|
|
|
|
|
// 当点击菜单项“字体大小”时
|
|
|
|
|
// 显示字体大小选择器,并根据当前字体大小ID显示相应的选择项
|
|
|
|
|
} else if (itemId == R.id.menu_font_size) { //设置字体大小
|
|
|
|
|
mFontSizeSelector.setVisibility(View.VISIBLE);
|
|
|
|
|
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);
|
|
|
|
|
} else if (itemId == R.id.menu_list_mode) {
|
|
|
|
|
// 当点击菜单项“模式切换”时
|
|
|
|
|
// 切换工作笔记的待办事项模式
|
|
|
|
|
mWorkingNote.setCheckListMode(mWorkingNote.getCheckListMode() == 0 ?
|
|
|
|
|
TextNote.MODE_CHECK_LIST : 0);
|
|
|
|
|
} else if (itemId == R.id.menu_share) {
|
|
|
|
|
// 当点击菜单项“分享”时
|
|
|
|
|
// 获取当前工作文本并进行分享
|
|
|
|
|
} else if (itemId == R.id.menu_share) { //分享
|
|
|
|
|
getWorkingText();
|
|
|
|
|
sendTo(this, mWorkingNote.getContent());
|
|
|
|
|
} else if (itemId == R.id.menu_send_to_desktop) {
|
|
|
|
|
// 当点击菜单项“发送到桌面”时
|
|
|
|
|
} else if (itemId == R.id.menu_send_to_desktop) { //发送到桌面
|
|
|
|
|
sendToDesktop();
|
|
|
|
|
} else if (itemId == R.id.menu_alert) {
|
|
|
|
|
// 当点击菜单项“提醒”时
|
|
|
|
|
// 设置闹钟提醒
|
|
|
|
|
} else if (itemId == R.id.menu_alert) { //设置提醒
|
|
|
|
|
setReminder();
|
|
|
|
|
} else if (itemId == R.id.menu_delete_remind) {
|
|
|
|
|
// 当点击菜单项“删除提醒”时
|
|
|
|
|
// 清除工作笔记的提醒日期和提醒标志
|
|
|
|
|
mWorkingNote.setAlertDate(0, false);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void setReminder() {
|
|
|
|
|
/*
|
|
|
|
|
* 这段 Java 代码实现了一个名为 `setReminder()` 的方法,用于设置笔记的提醒功能。以下是对该方法的解释:
|
|
|
|
|
1. 首先,创建一个 `DateTimePickerDialog` 对象 `d`,用于显示日期时间选择对话框。
|
|
|
|
|
2. 通过传递 System.currentTimeMillis() 方法的返回值,设置初始日期时间选择为当前时间。
|
|
|
|
|
3. 将一个匿名的 `OnDateTimeSetListener` 实例设置给 `d`,用于在用户选择日期时间后响应事件。
|
|
|
|
|
4. 在 `OnDateTimeSet` 方法中,获取用户选择的日期时间,
|
|
|
|
|
并通过调用 `mWorkingNote` 对象的 `setAlertDate()` 方法设置笔记的提醒日期时间。
|
|
|
|
|
5. 最后,通过调用 `d` 对象的 `show()` 方法,显示日期时间选择对话框。
|
|
|
|
|
综上,该方法实现了通过日期时间选择对话框设置笔记提醒功能的功能,用户能够通过该对话框选择想要提醒的日期时间点。
|
|
|
|
|
在用户选择日期时间后,将所选日期时间点保存到 `mWorkingNote` 对象中,以实现笔记的提醒功能。
|
|
|
|
|
*/
|
|
|
|
|
DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis());
|
|
|
|
|
d.setOnDateTimeSetListener(new OnDateTimeSetListener() {
|
|
|
|
|
public void OnDateTimeSet(AlertDialog dialog, long date) {
|
|
|
|
@ -696,23 +559,13 @@ public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
|
* and {@text/plain} type
|
|
|
|
|
*/
|
|
|
|
|
private void sendTo(Context context, String info) {
|
|
|
|
|
/*
|
|
|
|
|
这是一个名为 `sendTo()` 的私有方法,用于发送信息。
|
|
|
|
|
该方法接受两个参数,一个是上下文(`context`),一个是要发送的信息(`info`)。
|
|
|
|
|
方法的具体步骤如下:
|
|
|
|
|
1. 创建一个 `Intent` 对象,使用 `Intent.ACTION_SEND` 动作。这表示我们要发送数据。
|
|
|
|
|
2. 使用 `intent.putExtra()` 方法将要发送的文本数据添加到 `Intent` 中。
|
|
|
|
|
键为 `Intent.EXTRA_TEXT`,值为 `info`,即要发送的信息内容。
|
|
|
|
|
3. 使用 `intent.setType()` 方法指定发送的数据类型为纯文本("text/plain")。
|
|
|
|
|
4. 调用 `context.startActivity(intent)` 启动该意图,从而触发系统选择合适的应用程序来处理发送操作。
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Intent intent = new Intent(Intent.ACTION_SEND);
|
|
|
|
|
intent.putExtra(Intent.EXTRA_TEXT, info);
|
|
|
|
|
intent.setType("text/plain");
|
|
|
|
|
context.startActivity(intent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//创建新的便签函数
|
|
|
|
|
private void createNewNote() {
|
|
|
|
|
// Firstly, save current editing notes
|
|
|
|
|
saveNote();
|
|
|
|
@ -722,18 +575,9 @@ public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
|
Intent intent = new Intent(this, NoteEditActivity.class);
|
|
|
|
|
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
|
|
|
|
|
intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mWorkingNote.getFolderId());
|
|
|
|
|
startActivity(intent);/*
|
|
|
|
|
这段代码是一个方法 `createNewNote()` 的实现。下面是对代码的解释:
|
|
|
|
|
1. 首先,调用 `saveNote()` 方法保存当前正在编辑的笔记。
|
|
|
|
|
2. 为了安全起见,在开始新的笔记之前,调用 `finish()` 方法关闭当前的 Activity。
|
|
|
|
|
3. 创建一个新的 `Intent` 对象,将目标 Activity 设置为 `NoteEditActivity`(笔记编辑界面)。
|
|
|
|
|
4. 使用 `Intent.ACTION_INSERT_OR_EDIT` 设置操作,表示是插入或编辑操作。
|
|
|
|
|
5. 使用 `intent.putExtra()` 将当前笔记所属的文件夹的 ID 作为附加数据传递给 `NoteEditActivity`。
|
|
|
|
|
6. 最后,调用 `startActivity(intent)` 启动 `NoteEditActivity`。
|
|
|
|
|
这将打开一个新的笔记编辑界面,并根据传递的附加数据进行相应的操作。
|
|
|
|
|
*/
|
|
|
|
|
startActivity(intent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//删除当前工作的便签
|
|
|
|
|
private void deleteCurrentNote() {
|
|
|
|
|
if (mWorkingNote.existInDatabase()) {
|
|
|
|
|
HashSet<Long> ids = new HashSet<Long>();
|
|
|
|
@ -753,101 +597,81 @@ public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mWorkingNote.markDeleted(true);
|
|
|
|
|
/*
|
|
|
|
|
* 这段代码是一个方法 `deleteCurrentNote()` 的实现。下面是对代码的解释:
|
|
|
|
|
1. 首先,检查 `mWorkingNote` 是否存在于数据库中,即当前的笔记是否已经保存在数据库中。
|
|
|
|
|
2. 如果存在于数据库中,创建一个 `HashSet` 集合 `ids`,用于存储需要删除的笔记的 ID。
|
|
|
|
|
3. 获取当前笔记的 ID,并将其添加到 `ids` 集合中。
|
|
|
|
|
4. 检查当前笔记的 ID 是否等于 `Notes.ID_ROOT_FOLDER`,如果不是,将其添加到 `ids` 集合中。
|
|
|
|
|
5. 如果不是处于同步模式下(`isSyncMode()` 返回 `false`),
|
|
|
|
|
则调用 `DataUtils.batchDeleteNotes()` 方法批量删除数据库中的笔记。如果删除失败,打印错误日志信息。
|
|
|
|
|
6. 如果处于同步模式下,调用 `DataUtils.batchMoveToFolder()` 方法
|
|
|
|
|
将笔记批量移动到垃圾箱。如果移动失败,打印错误日志信息。
|
|
|
|
|
7. 调用 `mWorkingNote.markDeleted(true)` 方法,将当前笔记标记为已删除。
|
|
|
|
|
这段代码的作用是将当前的笔记标记为已删除,并根据不同的条件执行相应的操作:
|
|
|
|
|
如果不是同步模式,则删除数据库中的笔记;如果是同步模式,则将笔记移动到垃圾箱。
|
|
|
|
|
*/
|
|
|
|
|
mWorkingNote.markDeleted(true); //标记删除
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 判断是否为同步模式
|
|
|
|
|
private boolean isSyncMode() {
|
|
|
|
|
return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当闹钟提醒设置改变时的处理
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
// 如果工作笔记的ID大于0,则继续处理
|
|
|
|
|
if (mWorkingNote.getNoteId() > 0) {
|
|
|
|
|
// 创建AlarmReceiver的Intent
|
|
|
|
|
Intent intent = new Intent(this, AlarmReceiver.class);
|
|
|
|
|
intent.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mWorkingNote.getNoteId()));
|
|
|
|
|
// 创建用于广播的PendingIntent
|
|
|
|
|
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
|
|
|
|
|
// 获取AlarmManager实例
|
|
|
|
|
AlarmManager alarmManager = ((AlarmManager) getSystemService(ALARM_SERVICE));
|
|
|
|
|
// 显示提醒标题
|
|
|
|
|
showAlertHeader();
|
|
|
|
|
// 根据set参数判断是否设置或取消闹钟提醒
|
|
|
|
|
if(!set) {
|
|
|
|
|
alarmManager.cancel(pendingIntent); // 取消闹钟提醒
|
|
|
|
|
alarmManager.cancel(pendingIntent);
|
|
|
|
|
} else {
|
|
|
|
|
alarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent); // 设置闹钟提醒
|
|
|
|
|
alarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 如果工作笔记ID小于等于0,记录错误并显示提示
|
|
|
|
|
/**
|
|
|
|
|
* There is the condition that user has input nothing (the note is
|
|
|
|
|
* not worthy saving), we have no note id, remind the user that he
|
|
|
|
|
* should input something
|
|
|
|
|
*/
|
|
|
|
|
Log.e(TAG, "Clock alert setting error");
|
|
|
|
|
showToast(R.string.error_note_empty_for_clock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当小部件改变时的处理
|
|
|
|
|
public void onWidgetChanged() {
|
|
|
|
|
updateWidget(); // 更新小部件
|
|
|
|
|
updateWidget();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当文本编辑框内容删除时的处理
|
|
|
|
|
public void onEditTextDelete(int index, String text) {
|
|
|
|
|
int childCount = mEditTextList.getChildCount();
|
|
|
|
|
// 如果子View数量为1,则直接返回
|
|
|
|
|
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);
|
|
|
|
|
((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);
|
|
|
|
|
edit = (NoteEditText) mEditTextList.getChildAt(0).findViewById(
|
|
|
|
|
R.id.et_edit_text);
|
|
|
|
|
} else {
|
|
|
|
|
edit = (NoteEditText) mEditTextList.getChildAt(index - 1).findViewById(R.id.et_edit_text);
|
|
|
|
|
edit = (NoteEditText) mEditTextList.getChildAt(index - 1).findViewById(
|
|
|
|
|
R.id.et_edit_text);
|
|
|
|
|
}
|
|
|
|
|
int length = edit.length();
|
|
|
|
|
// 在编辑框末尾添加指定文本
|
|
|
|
|
edit.append(text);
|
|
|
|
|
edit.requestFocus();
|
|
|
|
|
edit.setSelection(length); // 设置光标位置
|
|
|
|
|
edit.setSelection(length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onEditTextEnter(int index, String text) {
|
|
|
|
|
/**
|
|
|
|
|
* 如果索引超出 mEditTextList 的范围,应该不会发生,进行调试检查
|
|
|
|
|
* Should not happen, check for debug
|
|
|
|
|
*/
|
|
|
|
|
if(index > mEditTextList.getChildCount()) {
|
|
|
|
|
Log.e(TAG, "Index out of mEditTextList boundrary, should not happen");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建新的编辑框视图并添加到 mEditTextList 中指定的位置
|
|
|
|
|
View view = getListItem(text, index);
|
|
|
|
|
mEditTextList.addView(view, index);
|
|
|
|
|
NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
|
|
|
|
@ -859,30 +683,23 @@ public void onEditTextEnter(int index, String text) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 切换到列表模式的处理方法
|
|
|
|
|
private void switchToListMode(String text) {
|
|
|
|
|
// 移除所有的编辑框视图
|
|
|
|
|
mEditTextList.removeAllViews();
|
|
|
|
|
// 将文本按换行符分割成字符串数组
|
|
|
|
|
String[] items = text.split("\n");
|
|
|
|
|
int index = 0;
|
|
|
|
|
for (String item : items) {
|
|
|
|
|
// 如果项不为空,则创建对应的编辑框视图并添加到 mEditTextList 中
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取包含用户查询结果高亮的 Spannable 对象
|
|
|
|
|
private Spannable getHighlightQueryResult(String fullText, String userQuery) {
|
|
|
|
|
SpannableString spannable = new SpannableString(fullText == null ? "" : fullText);
|
|
|
|
|
if (!TextUtils.isEmpty(userQuery)) {
|
|
|
|
@ -890,7 +707,6 @@ private Spannable getHighlightQueryResult(String fullText, String 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(),
|
|
|
|
@ -901,39 +717,26 @@ private Spannable getHighlightQueryResult(String fullText, String userQuery) {
|
|
|
|
|
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)) {
|
|
|
|
|
// 如果列表项以 "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)) {
|
|
|
|
|
// 如果列表项以 "unchecked" 标识开头,则设置复选框未选中状态,取消文本删除线,并去掉标识字符串
|
|
|
|
|
cb.setChecked(false);
|
|
|
|
|
edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
|
|
|
|
|
item = item.substring(TAG_UNCHECKED.length(), item.length()).trim();
|
|
|
|
@ -941,71 +744,37 @@ private View getListItem(String item, int index) {
|
|
|
|
|
|
|
|
|
|
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()) {
|
|
|
|
|
// 如果工作文本为空,并且未保存的文本中包含 "unchecked" 标识,则将其移除
|
|
|
|
|
mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ", ""));
|
|
|
|
|
mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ",
|
|
|
|
|
""));
|
|
|
|
|
}
|
|
|
|
|
// 设置编辑框内容,并将用户查询结果高亮显示
|
|
|
|
|
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
|
|
|
|
|
// 隐藏编辑框列表视图,显示笔记编辑视图
|
|
|
|
|
mEditTextList.setVisibility(View.GONE);
|
|
|
|
|
mNoteEditor.setVisibility(View.VISIBLE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean getWorkingText() {
|
|
|
|
|
/*
|
|
|
|
|
这是一个名为 `getWorkingText()` 的私有方法,返回一个布尔值。
|
|
|
|
|
该方法的作用是获取工作文本,具体步骤如下:
|
|
|
|
|
1. 首先,检查 `mWorkingNote` 对象的 `CheckListMode`
|
|
|
|
|
是否为 `TextNote.MODE_CHECK_LIST`。如果是,则进入列表模式的处理逻辑。
|
|
|
|
|
2. 创建一个 `StringBuilder` 对象 `sb`,用于拼接文本。
|
|
|
|
|
3. 遍历 `mEditTextList` 中的子视图(可能是多个文本编辑框):
|
|
|
|
|
- 获取子视图中的 `NoteEditText` 对象,用于获取文本内容。
|
|
|
|
|
- 如果 `edit.getText()` 不为空,表示该文本框有输入内容。
|
|
|
|
|
- 如果相应的复选框 `CheckBox` 被选中(`isChecked()` 返回 `true`),
|
|
|
|
|
将文本设为已选中状态,并向 `sb` 添加标记 `TAG_CHECKED`,文本内容,以及换行符。
|
|
|
|
|
同时将 `hasChecked` 设为 `true`。
|
|
|
|
|
- 否则,将文本设为未选中状态,并向 `sb` 添加标记 `TAG_UNCHECKED`,文本内容,以及换行符。
|
|
|
|
|
4. 将拼接好的文本 `sb.toString()` 设为 `mWorkingNote` 的工作文本。
|
|
|
|
|
5. 如果 `mWorkingNote` 的 `CheckListMode` 不是 `TextNote.MODE_CHECK_LIST`,
|
|
|
|
|
即非列表模式,则将 `mNoteEditor` 的文本内容设为 `mWorkingNote` 的工作文本。
|
|
|
|
|
6. 返回 `hasChecked`,该布尔值表示是否存在已选中的文本项。
|
|
|
|
|
*/
|
|
|
|
|
boolean hasChecked = false;
|
|
|
|
|
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
@ -1027,7 +796,7 @@ public void onCheckListModeChanged(int oldMode, int newMode) {
|
|
|
|
|
}
|
|
|
|
|
return hasChecked;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//保存便签
|
|
|
|
|
private boolean saveNote() {
|
|
|
|
|
getWorkingText();
|
|
|
|
|
boolean saved = mWorkingNote.saveNote();
|
|
|
|
@ -1046,24 +815,9 @@ public void onCheckListModeChanged(int oldMode, int newMode) {
|
|
|
|
|
|
|
|
|
|
private void sendToDesktop() {
|
|
|
|
|
/**
|
|
|
|
|
这段代码实现了一个名为 `sendToDesktop()` 的方法,用于将当前编辑的笔记发送到桌面上。
|
|
|
|
|
以下是对该方法的解释:
|
|
|
|
|
1. 首先,检查当前编辑的笔记 `mWorkingNote` 是否存在于数据库中。
|
|
|
|
|
如果笔记在数据库中不存在(即为新笔记),则调用 `saveNote()` 方法保存笔记。
|
|
|
|
|
2. 如果当前编辑的笔记已经存在于数据库中(即为已有的笔记),执行以下操作:
|
|
|
|
|
- 创建一个 `Intent` 对象 `sender`。
|
|
|
|
|
- 创建一个 `Intent` 对象 `shortcutIntent`,指定其启动目标为 `NoteEditActivity` 类。
|
|
|
|
|
- 为 `shortcutIntent` 指定动作 `Intent.ACTION_VIEW`,表示要进行查看操作。
|
|
|
|
|
- 通过 `putExtra()` 方法向 `shortcutIntent` 传递附加信息,包括笔记的唯一标识符(`NoteId`)。
|
|
|
|
|
- 通过 `sender.putExtra()` 方法向 `sender` 传递附加信息,包括快捷方式的意图(`shortcutIntent`)、
|
|
|
|
|
快捷方式的名称、快捷方式的图标资源和重复安装的标志等。
|
|
|
|
|
- 通过设置 `sender` 的动作为 `"com.android.launcher.action.INSTALL_SHORTCUT"`,表示要安装快捷方式。
|
|
|
|
|
- 调用 `showToast()` 方法显示一个消息提示框,提示用户笔记已进入桌面。
|
|
|
|
|
- 调用 `sendBroadcast()` 方法发送广播,通知系统安装快捷方式。
|
|
|
|
|
3. 如果当前编辑的笔记不存在(即为没有输入内容的空笔记),
|
|
|
|
|
则记录一个错误日志并调用 `showToast()` 方法显示一个错误提示框,提醒用户输入内容。
|
|
|
|
|
4. 方法执行结束。
|
|
|
|
|
综上,该方法的功能是将当前编辑的笔记发送到桌面上,并根据笔记的状态进行相应的处理,如保存新笔记、创建快捷方式等。
|
|
|
|
|
* Before send message to home, we should make sure that current
|
|
|
|
|
* editing note is exists in databases. So, for new note, firstly
|
|
|
|
|
* save it
|
|
|
|
|
*/
|
|
|
|
|
if (!mWorkingNote.existInDatabase()) {
|
|
|
|
|
saveNote();
|
|
|
|
@ -1095,21 +849,17 @@ public void onCheckListModeChanged(int oldMode, int newMode) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
return content.length() > SHORTCUT_ICON_TITLE_MAX_LEN ? content.substring(0,
|
|
|
|
|
SHORTCUT_ICON_TITLE_MAX_LEN) : content;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void showToast(int resId) {
|
|
|
|
|
// 显示一个短持续时间的Toast消息,消息内容为给定的资源ID的字符串
|
|
|
|
|
showToast(resId, Toast.LENGTH_SHORT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void showToast(int resId, int duration) {
|
|
|
|
|
// 显示一个具有自定义持续时间的Toast消息,消息内容为给定的资源ID的字符串
|
|
|
|
|
// Toast消息在当前的上下文中显示
|
|
|
|
|
Toast.makeText(this, resId, duration).show();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|