From d6c314165fb69d3540005dc708a6d26d439ace42 Mon Sep 17 00:00:00 2001
From: machao <2184367881@qq.com>
Date: Sun, 12 Jan 2025 21:51:07 +0800
Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=90=8E=E7=9A=84ui?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/ui(m)/NotesListActivity.java | 1623 +++++++++++++++---------
src/ui(m)/NotesPreferenceActivity.java | 443 ++++---
2 files changed, 1235 insertions(+), 831 deletions(-)
diff --git a/src/ui(m)/NotesListActivity.java b/src/ui(m)/NotesListActivity.java
index b5291ec..37bc24b 100644
--- a/src/ui(m)/NotesListActivity.java
+++ b/src/ui(m)/NotesListActivity.java
@@ -1,10 +1,12 @@
/*
* 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
+ * 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.
@@ -12,12 +14,70 @@
* limitations under the License.
*/
+// 导入 Android 相关的类库
package net.micode.notes.ui;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
-// ...(省略其他import)
+import android.appwidget.AppWidgetManager;
+import android.content.AsyncQueryHandler;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.ActionMode;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.Display;
+import android.view.HapticFeedbackConstants;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnCreateContextMenuListener;
+import android.view.View.OnTouchListener;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemLongClickListener;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.PopupMenu;
+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.NoteColumns;
+import net.micode.notes.gtask.remote.GTaskSyncService;
+import net.micode.notes.model.WorkingNote;
+import net.micode.notes.tool.BackupUtils;
+import net.micode.notes.tool.DataUtils;
+import net.micode.notes.tool.ResourceParser;
+import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute;
+import net.micode.notes.widget.NoteWidgetProvider_2x;
+import net.micode.notes.widget.NoteWidgetProvider_4x;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.HashSet;
// NotesListActivity类继承自Activity,用于展示笔记列表
public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener {
@@ -34,6 +94,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private enum ListEditState {
NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER
};
+
// 成员变量声明
private ListEditState mState;
private BackgroundQueryHandler mBackgroundQueryHandler;
@@ -52,12 +113,13 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private NoteItemData mFocusNoteDataItem;
private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=?";
private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns.TYPE + "<>"
- + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" + " OR ("
- + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND "
+ + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" + " OR ("
+ + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND "
+ NoteColumns.NOTES_COUNT + ">0)";
private final static int REQUEST_CODE_OPEN_NODE = 102;
private final static int REQUEST_CODE_NEW_NODE = 103;
+ // Activity 创建时调用的方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -69,722 +131,1041 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
*/
setAppInfoFromRawRes();
}
+@Override
+protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ // 检查请求码和结果码,确保是打开或创建笔记项的操作,并且操作成功
+ if (resultCode == RESULT_OK
+ && (requestCode == REQUEST_CODE_OPEN_NODE || requestCode == REQUEST_CODE_NEW_NODE)) {
+ // 重置适配器的游标,以刷新列表
+ mNotesListAdapter.changeCursor(null);
+ } else {
+ // 调用父类的onActivityResult方法处理其他情况
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+}
- /**
- * 从raw资源文件中读取介绍信息,并将其保存为笔记
- */
- private void setAppInfoFromRawRes() {
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
- if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) {
- StringBuilder sb = new StringBuilder();
- InputStream in = null;
- try {
- in = getResources().openRawResource(R.raw.introduction);
- if (in != null) {
- InputStreamReader isr = new InputStreamReader(in);
- BufferedReader br = new BufferedReader(isr);
- char [] buf = new char[1024];
- int len = 0;
- while ((len = br.read(buf)) > 0) {
- sb.append(buf, 0, len);
- }
- } else {
- Log.e(TAG, "Read introduction file error");
- return;
+private void setAppInfoFromRawRes() {
+ // 获取默认的SharedPreferences实例
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
+ // 检查是否已经添加了介绍信息
+ if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) {
+ StringBuilder sb = new StringBuilder(); // 用于构建介绍信息的字符串
+ InputStream in = null; // 用于读取raw资源文件的输入流
+ try {
+ // 打开raw资源文件
+ in = getResources().openRawResource(R.raw.introduction);
+ if (in != null) {
+ InputStreamReader isr = new InputStreamReader(in); // 将输入流转换为字符流
+ BufferedReader br = new BufferedReader(isr); // 用于逐行读取字符流
+ char[] buf = new char[1024]; // 读取缓冲区
+ int len = 0;
+ // 逐行读取文件内容并追加到StringBuilder中
+ while ((len = br.read(buf)) > 0) {
+ sb.append(buf, 0, len);
}
- } catch (IOException e) {
- e.printStackTrace();
- return;
- } finally {
- if(in != null) {
- try {
- in.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
-
- WorkingNote note = WorkingNote.createEmptyNote(this, Notes.ID_ROOT_FOLDER,
- AppWidgetManager.INVALID_APPWIDGET_ID, Notes.TYPE_WIDGET_INVALIDE,
- ResourceParser.RED);
- note.setWorkingText(sb.toString());
- if (note.saveNote()) {
- sp.edit().putBoolean(PREFERENCE_ADD_INTRODUCTION, true).commit();
} else {
- Log.e(TAG, "Save introduction note error");
+ // 如果输入流为空,记录错误信息
+ Log.e(TAG, "Read introduction file error");
return;
}
+ } catch (IOException e) {
+ // 捕获并记录IO异常
+ e.printStackTrace();
+ return;
+ } finally {
+ // 确保输入流在使用后关闭
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ // 捕获并记录关闭输入流时的IO异常
+ e.printStackTrace();
+ }
+ }
}
- }
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode == RESULT_OK
- && (requestCode == REQUEST_CODE_OPEN_NODE || requestCode == REQUEST_CODE_NEW_NODE)) {
- mNotesListAdapter.changeCursor(null);
+ // 创建一个新的笔记对象
+ WorkingNote note = WorkingNote.createEmptyNote(this, Notes.ID_ROOT_FOLDER,
+ AppWidgetManager.INVALID_APPWIDGET_ID, Notes.TYPE_WIDGET_INVALIDE,
+ ResourceParser.RED);
+ // 设置笔记的文本内容为读取到的介绍信息
+ note.setWorkingText(sb.toString());
+ // 保存笔记
+ if (note.saveNote()) {
+ // 如果保存成功,更新SharedPreferences,标记已经添加了介绍信息
+ sp.edit().putBoolean(PREFERENCE_ADD_INTRODUCTION, true).commit();
} else {
- super.onActivityResult(requestCode, resultCode, data);
+ // 如果保存失败,记录错误信息
+ Log.e(TAG, "Save introduction note error");
+ return;
}
}
+}
+@Override
+protected void onStart() {
+ super.onStart();
+ // 当Activity启动时,开始异步查询笔记列表
+ startAsyncNotesListQuery();
+}
- /**
- * 初始化活动所需的资源,包括内容解析器、适配器、列表视图等
- */
- private void initResources() {
- mContentResolver = this.getContentResolver();
- mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver());
- mCurrentFolderId = Notes.ID_ROOT_FOLDER;
- mNotesListView = (ListView) findViewById(R.id.notes_list);
- mNotesListView.addFooterView(LayoutInflater.from(this).inflate(R.layout.note_list_footer, null), null, false);
- mNotesListView.setOnItemClickListener(new OnListItemClickListener());
- mNotesListView.setOnItemLongClickListener(this);
- mNotesListAdapter = new NotesListAdapter(this);
- mNotesListView.setAdapter(mNotesListAdapter);
- mAddNewNote = (Button) findViewById(R.id.btn_new_note);
- mAddNewNote.setOnClickListener(this);
- mAddNewNote.setOnTouchListener(new NewNoteOnTouchListener());
- mDispatch = false;
- mDispatchY = 0;
- mOriginY = 0;
- mTitleBar = (TextView) findViewById(R.id.tv_title_bar);
- mState = ListEditState.NOTE_LIST;
- mModeCallBack = new ModeCallback();
- }
- // 内部类,用于处理多点触控事件,当用户触摸“新建笔记”按钮时的特殊处理
- private class NewNoteOnTouchListener implements OnTouchListener {
- public boolean onTouch(View v, MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN: {
- // 计算屏幕高度和“新建笔记”按钮的高度差
- Display display = getWindowManager().getDefaultDisplay();
- int screenHeight = display.getHeight();
- int newNoteViewHeight = mAddNewNote.getHeight();
- int start = screenHeight - newNoteViewHeight;
- int eventY = start + (int) event.getY();
- // 根据UI设计师的要求,对“新建笔记”按钮的透明部分进行特殊处理
- if (event.getY() < (event.getX() * (-0.12) + 94)) {
- View view = mNotesListView.getChildAt(mNotesListView.getChildCount() - 1
- - mNotesListView.getFooterViewsCount());
- if (view != null && view.getBottom() > start
- && (view.getTop() < (start + 94))) {
- mOriginY = (int) event.getY();
- mDispatchY = eventY;
- event.setLocation(event.getX(), mDispatchY);
- mDispatch = true;
- return mNotesListView.dispatchTouchEvent(event);
- }
- }
- break;
- }
- case MotionEvent.ACTION_MOVE: {
- if (mDispatch) {
- mDispatchY += (int) event.getY() - mOriginY;
- event.setLocation(event.getX(), mDispatchY);
- return mNotesListView.dispatchTouchEvent(event);
- }
- break;
- }
- default: {
- if (mDispatch) {
- event.setLocation(event.getX(), mDispatchY);
- mDispatch = false;
- return mNotesListView.dispatchTouchEvent(event);
- }
- break;
- }
- }
- return false;
- }
- };
+private void initResources() {
+ // 初始化内容解析器
+ mContentResolver = this.getContentResolver();
+ // 创建异步查询处理器
+ mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver());
+ // 设置当前文件夹ID为根文件夹ID
+ mCurrentFolderId = Notes.ID_ROOT_FOLDER;
+ // 获取笔记列表视图
+ mNotesListView = (ListView) findViewById(R.id.notes_list);
+ // 向列表视图添加一个底部视图
+ mNotesListView.addFooterView(LayoutInflater.from(this).inflate(R.layout.note_list_footer, null),
+ null, false);
+ // 设置列表项点击事件监听器
+ mNotesListView.setOnItemClickListener(new OnListItemClickListener());
+ // 设置列表项长按事件监听器
+ mNotesListView.setOnItemLongClickListener(this);
+ // 创建笔记列表适配器
+ mNotesListAdapter = new NotesListAdapter(this);
+ // 设置适配器到列表视图
+ mNotesListView.setAdapter(mNotesListAdapter);
+ // 获取新建笔记按钮
+ mAddNewNote = (Button) findViewById(R.id.btn_new_note);
+ // 设置新建笔记按钮的点击事件监听器
+ mAddNewNote.setOnClickListener(this);
+ // 设置新建笔记按钮的触摸事件监听器
+ mAddNewNote.setOnTouchListener(new NewNoteOnTouchListener());
+ // 初始化多点触控事件处理变量
+ mDispatch = false;
+ mDispatchY = 0;
+ mOriginY = 0;
+ // 获取标题栏
+ mTitleBar = (TextView) findViewById(R.id.tv_title_bar);
+ // 设置当前列表编辑状态为笔记列表
+ mState = ListEditState.NOTE_LIST;
+ // 创建多选模式回调
+ mModeCallBack = new ModeCallback();
+}
- /**
- * 启动异步查询,获取笔记列表
- */
- private void startAsyncNotesListQuery() {
- String selection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION
- : NORMAL_SELECTION;
- mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
- Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[] {
- String.valueOf(mCurrentFolderId)
- }, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
- }
+private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener {
+ private DropdownMenu mDropDownMenu; // 下拉菜单
+ private ActionMode mActionMode; // 多选模式
+ private MenuItem mMoveMenu; // 移动菜单项
- // 异步查询处理器,处理查询完成事件
- private final class BackgroundQueryHandler extends AsyncQueryHandler {
- public BackgroundQueryHandler(ContentResolver contentResolver) {
- super(contentResolver);
+ // 创建多选模式时调用
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ // 加载菜单资源
+ getMenuInflater().inflate(R.menu.note_list_options, menu);
+ // 设置删除菜单项的点击事件监听器
+ menu.findItem(R.id.delete).setOnMenuItemClickListener(this);
+ // 获取移动菜单项
+ mMoveMenu = menu.findItem(R.id.move);
+ // 根据条件设置移动菜单项的可见性
+ if (mFocusNoteDataItem.getParentId() == Notes.ID_CALL_RECORD_FOLDER
+ || DataUtils.getUserFolderCount(mContentResolver) == 0) {
+ mMoveMenu.setVisible(false);
+ } else {
+ mMoveMenu.setVisible(true);
+ mMoveMenu.setOnMenuItemClickListener(this);
}
+ // 保存多选模式实例
+ mActionMode = mode;
+ // 设置适配器为多选模式
+ mNotesListAdapter.setChoiceMode(true);
+ // 禁用列表项的长按事件
+ mNotesListView.setLongClickable(false);
+ // 隐藏新建笔记按钮
+ mAddNewNote.setVisibility(View.GONE);
- @Override
- protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
- switch (token) {
- case FOLDER_NOTE_LIST_QUERY_TOKEN:
- mNotesListAdapter.changeCursor(cursor);
- break;
- case FOLDER_LIST_QUERY_TOKEN:
- if (cursor != null && cursor.getCount() > 0) {
- showFolderListMenu(cursor);
- } else {
- Log.e(TAG, "Query folder failed");
- }
- break;
- default:
- return;
+ // 加载自定义视图
+ View customView = LayoutInflater.from(NotesListActivity.this).inflate(
+ R.layout.note_list_dropdown_menu, null);
+ mode.setCustomView(customView);
+ // 创建下拉菜单
+ mDropDownMenu = new DropdownMenu(NotesListActivity.this,
+ (Button) customView.findViewById(R.id.selection_menu),
+ R.menu.note_list_dropdown);
+ // 设置下拉菜单项的点击事件监听器
+ mDropDownMenu.setOnDropdownMenuItemClickListener(new PopupMenu.OnMenuItemClickListener(){
+ public boolean onMenuItemClick(MenuItem item) {
+ // 切换全选/取消全选状态
+ mNotesListAdapter.selectAll(!mNotesListAdapter.isAllSelected());
+ // 更新菜单状态
+ updateMenu();
+ return true;
}
- }
+ });
+ return true;
}
- /**
- * 显示文件夹列表菜单,允许用户选择目标文件夹
- */
- private void showFolderListMenu(Cursor cursor) {
- AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
- builder.setTitle(R.string.menu_title_select_folder);
- final FoldersListAdapter adapter = new FoldersListAdapter(this, cursor);
- builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- DataUtils.batchMoveToFolder(mContentResolver,
- mNotesListAdapter.getSelectedItemIds(), adapter.getItemId(which));
- Toast.makeText(
- NotesListActivity.this,
- getString(R.string.format_move_notes_to_folder,
- mNotesListAdapter.getSelectedCount(),
- adapter.getFolderName(NotesListActivity.this, which)),
- Toast.LENGTH_SHORT).show();
- mModeCallBack.finishActionMode();
+ // 更新菜单状态
+ private void updateMenu() {
+ int selectedCount = mNotesListAdapter.getSelectedCount();
+ // 更新下拉菜单的标题
+ String format = getResources().getString(R.string.menu_select_title, selectedCount);
+ mDropDownMenu.setTitle(format);
+ // 获取全选/取消全选菜单项
+ MenuItem item = mDropDownMenu.findItem(R.id.action_select_all);
+ if (item != null) {
+ if (mNotesListAdapter.isAllSelected()) {
+ item.setChecked(true);
+ item.setTitle(R.string.menu_deselect_all);
+ } else {
+ item.setChecked(false);
+ item.setTitle(R.string.menu_select_all);
}
- });
- builder.show();
- }
- /**
- * 创建新笔记的函数
- */
- private void createNewNote() {
- Intent intent = new Intent(this, NoteEditActivity.class);
- intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
- intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mCurrentFolderId);
- this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE);
+ }
}
- /**
- * 批量删除笔记的函数
- */
- private void batchDelete() {
- new AsyncTask>() {
- protected HashSet doInBackground(Void... unused) {
- HashSet widgets = mNotesListAdapter.getSelectedWidget();
- if (!isSyncMode()) {
- // 如果不是同步模式,直接删除笔记
- if (DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter
- .getSelectedItemIds())) {
- } else {
- Log.e(TAG, "Delete notes error, should not happens");
- }
- } else {
- // 如果是同步模式,将删除的笔记移动到回收站文件夹
- if (!DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter
- .getSelectedItemIds(), Notes.ID_TRASH_FOLER)) {
- Log.e(TAG, "Move notes to trash folder error, should not happens");
- }
- }
- return widgets;
- }
+ // 准备多选模式时调用
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ // TODO Auto-generated method stub
+ return false;
+ }
- @Override
- protected void onPostExecute(HashSet widgets) {
- if (widgets != null) {
- for (AppWidgetAttribute widget : widgets) {
- if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID
- && widget.widgetType != Notes.TYPE_WIDGET_INVALIDE) {
- updateWidget(widget.widgetId, widget.widgetType);
- }
- }
- }
- mModeCallBack.finishActionMode();
- }
- }.execute();
+ // 点击多选模式菜单项时调用
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ // TODO Auto-generated method stub
+ return false;
}
- /**
- * 删除文件夹的函数
- */
- private void deleteFolder(long folderId) {
- if (folderId == Notes.ID_ROOT_FOLDER) {
- Log.e(TAG, "Wrong folder id, should not happen " + folderId);
- return;
- }
+ // 多选模式销毁时调用
+ public void onDestroyActionMode(ActionMode mode) {
+ // 重置适配器为非多选模式
+ mNotesListAdapter.setChoiceMode(false);
+ // 启用列表项的长按事件
+ mNotesListView.setLongClickable(true);
+ // 显示新建笔记按钮
+ mAddNewNote.setVisibility(View.VISIBLE);
+ }
- HashSet ids = new HashSet();
- ids.add(folderId);
- HashSet widgets = DataUtils.getFolderNoteWidget(mContentResolver,
- folderId);
- if (!isSyncMode()) {
- // 如果不是同步模式,直接删除文件夹
- DataUtils.batchDeleteNotes(mContentResolver, ids);
- } else {
- // 如果是同步模式,将删除的文件夹移动到回收站文件夹
- DataUtils.batchMoveToFolder(mContentResolver, ids, Notes.ID_TRASH_FOLER);
- }
- if (widgets != null) {
- for (AppWidgetAttribute widget : widgets) {
- if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID
- && widget.widgetType != Notes.TYPE_WIDGET_INVALIDE) {
- updateWidget(widget.widgetId, widget.widgetType);
- }
- }
- }
+ // 结束多选模式
+ public void finishActionMode() {
+ mActionMode.finish();
}
- /**
- * 打开笔记项的函数
- */
- private void openNode(NoteItemData data) {
- Intent intent = new Intent(this, NoteEditActivity.class);
- intent.setAction(Intent.ACTION_VIEW);
- intent.putExtra(Intent.EXTRA_UID, data.getId());
- this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE);
+ // 列表项选中状态改变时调用
+ public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
+ boolean checked) {
+ // 更新适配器的选中状态
+ mNotesListAdapter.setCheckedItem(position, checked);
+ // 更新菜单状态
+ updateMenu();
}
- /**
- * 打开文件夹的函数
- */
- private void openFolder(NoteItemData data) {
- mCurrentFolderId = data.getId();
- startAsyncNotesListQuery();
- if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
- mState = ListEditState.CALL_RECORD_FOLDER;
- mAddNewNote.setVisibility(View.GONE);
- } else {
- mState = ListEditState.SUB_FOLDER;
+ // 菜单项点击事件
+ public boolean onMenuItemClick(MenuItem item) {
+ // 检查是否有选中的项
+ if (mNotesListAdapter.getSelectedCount() == 0) {
+ // 显示提示信息
+ Toast.makeText(NotesListActivity.this, getString(R.string.menu_select_none),
+ Toast.LENGTH_SHORT).show();
+ return true;
}
- if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
- mTitleBar.setText(R.string.call_record_folder_name);
- } else {
- mTitleBar.setText(data.getSnippet());
- }
- mTitleBar.setVisibility(View.VISIBLE);
}
+}
+// 菜单项点击事件处理
+public boolean onMenuItemClick(MenuItem item) {
+ // 根据菜单项的ID进行处理
+ switch (item.getItemId()) {
+ case R.id.delete:
+ // 创建一个AlertDialog.Builder实例
+ AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.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_notes,
+ mNotesListAdapter.getSelectedCount()));
+ // 设置确认按钮
+ builder.setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int which) {
+ // 调用批量删除方法
+ batchDelete();
+ }
+ });
+ // 设置取消按钮
+ builder.setNegativeButton(android.R.string.cancel, null);
+ // 显示对话框
+ builder.show();
+ break;
+ case R.id.move:
+ // 开始查询目标文件夹
+ startQueryDestinationFolders();
+ break;
+ default:
+ // 如果不是已知的菜单项,返回false
+ return false;
+ }
+ // 处理成功,返回true
+ return true;
+}
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.btn_new_note:
- createNewNote();
+// 内部类,用于处理多点触控事件,当用户触摸“新建笔记”按钮时的特殊处理
+private class NewNoteOnTouchListener implements OnTouchListener {
+ public boolean onTouch(View v, MotionEvent event) {
+ // 根据事件类型进行处理
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN: {
+ // 获取屏幕高度
+ Display display = getWindowManager().getDefaultDisplay();
+ int screenHeight = display.getHeight();
+ // 获取“新建笔记”按钮的高度
+ int newNoteViewHeight = mAddNewNote.getHeight();
+ // 计算“新建笔记”按钮的起始位置
+ int start = screenHeight - newNoteViewHeight;
+ // 计算事件的Y坐标
+ int eventY = start + (int) event.getY();
+ /**
+ * 如果当前状态是子文件夹状态,减去标题栏的高度
+ */
+ if (mState == ListEditState.SUB_FOLDER) {
+ eventY -= mTitleBar.getHeight();
+ start -= mTitleBar.getHeight();
+ }
+ /**
+ * HACKME: 当点击“新建笔记”按钮的透明部分时,将事件分发给背后的列表视图。
+ * “新建笔记”按钮的透明部分可以用公式 y=-0.12x+94(单位:像素)和按钮的顶部线表示。
+ * 坐标基于“新建笔记”按钮的左侧。94表示透明部分的最大高度。
+ * 注意:如果按钮的背景发生变化,公式也应该相应变化。这是非常糟糕的,只是为了满足UI设计师的强烈要求。
+ */
+ if (event.getY() < (event.getX() * (-0.12) + 94)) {
+ // 获取列表视图的最后一个子视图
+ View view = mNotesListView.getChildAt(mNotesListView.getChildCount() - 1
+ - mNotesListView.getFooterViewsCount());
+ if (view != null && view.getBottom() > start
+ && (view.getTop() < (start + 94))) {
+ // 记录初始Y坐标
+ mOriginY = (int) event.getY();
+ mDispatchY = eventY;
+ // 重新设置事件的Y坐标
+ event.setLocation(event.getX(), mDispatchY);
+ // 标记为需要分发
+ mDispatch = true;
+ // 分发事件到列表视图
+ return mNotesListView.dispatchTouchEvent(event);
+ }
+ }
break;
- default:
+ }
+ case MotionEvent.ACTION_MOVE: {
+ // 如果需要分发
+ if (mDispatch) {
+ // 更新事件的Y坐标
+ mDispatchY += (int) event.getY() - mOriginY;
+ event.setLocation(event.getX(), mDispatchY);
+ // 分发事件到列表视图
+ return mNotesListView.dispatchTouchEvent(event);
+ }
+ break;
+ }
+ default: {
+ // 如果需要分发
+ if (mDispatch) {
+ // 重新设置事件的Y坐标
+ event.setLocation(event.getX(), mDispatchY);
+ // 重置分发标志
+ mDispatch = false;
+ // 分发事件到列表视图
+ return mNotesListView.dispatchTouchEvent(event);
+ }
break;
+ }
}
+ // 事件未处理,返回false
+ return false;
}
+}
- /**
- * 显示软键盘的函数
- */
- private void showSoftInput() {
- InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- if (inputMethodManager != null) {
- inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
- }
- }
+// 启动异步查询,获取笔记列表
+private void startAsyncNotesListQuery() {
+ // 根据当前文件夹ID选择查询条件
+ String selection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION
+ : NORMAL_SELECTION;
+ // 开始异步查询
+ mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
+ Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[] {
+ String.valueOf(mCurrentFolderId)
+ }, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
+}
- /**
- * 隐藏软键盘的函数
- */
- private void hideSoftInput(View view) {
- InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
+// 异步查询处理器,处理查询完成事件
+private final class BackgroundQueryHandler extends AsyncQueryHandler {
+ public BackgroundQueryHandler(ContentResolver contentResolver) {
+ super(contentResolver);
}
-
- /**
- * 显示创建或修改文件夹对话框的函数
- */
- private void showCreateOrModifyFolderDialog(final boolean create) {
- final AlertDialog.Builder builder = new AlertDialog.Builder(this);
- View view = LayoutInflater.from(this).inflate(R.layout.dialog_edit_text, null);
- final EditText etName = (EditText) view.findViewById(R.id.et_foler_name);
- showSoftInput();
- if (!create) {
- if (mFocusNoteDataItem != null) {
- etName.setText(mFocusNoteDataItem.getSnippet());
- builder.setTitle(getString(R.string.menu_folder_change_name));
+}
+@Override
+protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
+ // 根据查询令牌处理查询结果
+ switch (token) {
+ case FOLDER_NOTE_LIST_QUERY_TOKEN:
+ // 更新笔记列表适配器的游标
+ mNotesListAdapter.changeCursor(cursor);
+ break;
+ case FOLDER_LIST_QUERY_TOKEN:
+ // 如果查询到文件夹列表
+ if (cursor != null && cursor.getCount() > 0) {
+ // 显示文件夹列表菜单
+ showFolderListMenu(cursor);
} else {
- Log.e(TAG, "The long click data item is null");
- return;
+ // 记录查询失败的错误信息
+ Log.e(TAG, "Query folder failed");
}
- } else {
- etName.setText("");
- builder.setTitle(this.getString(R.string.menu_create_folder));
+ break;
+ default:
+ // 未知令牌,直接返回
+ return;
+ }
+}
+
+// 显示文件夹列表菜单
+private void showFolderListMenu(Cursor cursor) {
+ // 创建AlertDialog.Builder实例
+ AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
+ // 设置对话框标题
+ builder.setTitle(R.string.menu_title_select_folder);
+ // 创建文件夹列表适配器
+ final FoldersListAdapter adapter = new FoldersListAdapter(this, cursor);
+ // 设置适配器和点击事件监听器
+ builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // 批量移动选中的笔记到目标文件夹
+ DataUtils.batchMoveToFolder(mContentResolver,
+ mNotesListAdapter.getSelectedItemIds(), adapter.getItemId(which));
+ // 显示移动成功的提示信息
+ Toast.makeText(
+ NotesListActivity.this,
+ getString(R.string.format_move_notes_to_folder,
+ mNotesListAdapter.getSelectedCount(),
+ adapter.getFolderName(NotesListActivity.this, which)),
+ Toast.LENGTH_SHORT).show();
+ // 结束多选模式
+ mModeCallBack.finishActionMode();
}
+ });
+ // 显示对话框
+ builder.show();
+}
- builder.setPositiveButton(android.R.string.ok, null);
- builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- hideSoftInput(etName);
- }
- });
+// 创建新笔记
+private void createNewNote() {
+ // 创建Intent,启动NoteEditActivity
+ Intent intent = new Intent(this, NoteEditActivity.class);
+ // 设置Action为插入或编辑
+ intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
+ // 传递当前文件夹ID
+ intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mCurrentFolderId);
+ // 启动Activity并等待结果
+ this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE);
+}
- final Dialog dialog = builder.setView(view).show();
- final Button positive = (Button)dialog.findViewById(android.R.id.button1);
- positive.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- hideSoftInput(etName);
- String name = etName.getText().toString();
- if (DataUtils.checkVisibleFolderName(mContentResolver, name)) {
- Toast.makeText(NotesListActivity.this, getString(R.string.folder_exist, name),
- Toast.LENGTH_LONG).show();
- etName.setSelection(0, etName.length());
- return;
+// 批量删除笔记
+private void batchDelete() {
+ // 创建异步任务
+ new AsyncTask>() {
+ protected HashSet doInBackground(Void... unused) {
+ // 获取选中的小部件属性
+ HashSet widgets = mNotesListAdapter.getSelectedWidget();
+ if (!isSyncMode()) {
+ // 如果不是同步模式,直接删除笔记
+ if (DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter.getSelectedItemIds())) {
+ } else {
+ // 记录删除失败的错误信息
+ Log.e(TAG, "Delete notes error, should not happens");
}
- if (!create) {
- if (!TextUtils.isEmpty(name)) {
- ContentValues values = new ContentValues();
- values.put(NoteColumns.SNIPPET, name);
- values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
- values.put(NoteColumns.LOCAL_MODIFIED, 1);
- mContentResolver.update(Notes.CONTENT_NOTE_URI, values, NoteColumns.ID
- + "=?", new String[] {
- String.valueOf(mFocusNoteDataItem.getId())
- });
- }
- } else if (!TextUtils.isEmpty(name)) {
- ContentValues values = new ContentValues();
- values.put(NoteColumns.SNIPPET, name);
- values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
- mContentResolver.insert(Notes.CONTENT_NOTE_URI, values);
+ } else {
+ // 如果是同步模式,将删除的笔记移动到回收站文件夹
+ if (!DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter.getSelectedItemIds(), Notes.ID_TRASH_FOLER)) {
+ // 记录移动失败的错误信息
+ Log.e(TAG, "Move notes to trash folder error, should not happens");
}
- dialog.dismiss();
}
- });
-
- if (TextUtils.isEmpty(etName.getText())) {
- positive.setEnabled(false);
+ return widgets;
}
- etName.addTextChangedListener(new TextWatcher() {
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- // TODO Auto-generated method stub
- }
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- if (TextUtils.isEmpty(etName.getText())) {
- positive.setEnabled(false);
- } else {
- positive.setEnabled(true);
+ @Override
+ protected void onPostExecute(HashSet widgets) {
+ // 更新小部件
+ if (widgets != null) {
+ for (AppWidgetAttribute widget : widgets) {
+ if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID
+ && widget.widgetType != Notes.TYPE_WIDGET_INVALIDE) {
+ updateWidget(widget.widgetId, widget.widgetType);
+ }
}
}
+ // 结束多选模式
+ mModeCallBack.finishActionMode();
+ }
+ }.execute();
+}
- public void afterTextChanged(Editable s) {
- // TODO Auto-generated method stub
- }
- });
+// 删除文件夹
+private void deleteFolder(long folderId) {
+ if (folderId == Notes.ID_ROOT_FOLDER) {
+ // 如果尝试删除根文件夹,记录错误信息
+ Log.e(TAG, "Wrong folder id, should not happen " + folderId);
+ return;
}
- @Override
- public void onBackPressed() {
- switch (mState) {
- case SUB_FOLDER:
- mCurrentFolderId = Notes.ID_ROOT_FOLDER;
- mState = ListEditState.NOTE_LIST;
- startAsyncNotesListQuery();
- mTitleBar.setVisibility(View.GONE);
- break;
- case CALL_RECORD_FOLDER:
- mCurrentFolderId = Notes.ID_ROOT_FOLDER;
- mState = ListEditState.NOTE_LIST;
- mAddNewNote.setVisibility(View.VISIBLE);
- mTitleBar.setVisibility(View.GONE);
- startAsyncNotesListQuery();
- break;
- case NOTE_LIST:
- super.onBackPressed();
- break;
- default:
- break;
- }
+ // 创建文件夹ID集合
+ HashSet ids = new HashSet();
+ ids.add(folderId);
+ // 获取文件夹的小部件属性
+ HashSet widgets = DataUtils.getFolderNoteWidget(mContentResolver, folderId);
+ if (!isSyncMode()) {
+ // 如果不是同步模式,直接删除文件夹
+ DataUtils.batchDeleteNotes(mContentResolver, ids);
+ } else {
+ // 如果是同步模式,将删除的文件夹移动到回收站文件夹
+ DataUtils.batchMoveToFolder(mContentResolver, ids, Notes.ID_TRASH_FOLER);
}
-
- /**
- * 更新Widget的函数
- */
- private void updateWidget(int appWidgetId, int appWidgetType) {
- Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
- if (appWidgetType == Notes.TYPE_WIDGET_2X) {
- intent.setClass(this, NoteWidgetProvider_2x.class);
- } else if (appWidgetType == Notes.TYPE_WIDGET_4X) {
- intent.setClass(this, NoteWidgetProvider_4x.class);
- } else {
- Log.e(TAG, "Unspported widget type");
- return;
+ // 更新小部件
+ if (widgets != null) {
+ for (AppWidgetAttribute widget : widgets) {
+ if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID
+ && widget.widgetType != Notes.TYPE_WIDGET_INVALIDE) {
+ updateWidget(widget.widgetId, widget.widgetType);
+ }
}
+ }
+}
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
- appWidgetId
- });
+// 打开笔记项
+private void openNode(NoteItemData data) {
+ // 创建Intent,启动NoteEditActivity
+ Intent intent = new Intent(this, NoteEditActivity.class);
+ // 设置Action为查看
+ intent.setAction(Intent.ACTION_VIEW);
+ // 传递笔记ID
+ intent.putExtra(Intent.EXTRA_UID, data.getId());
+ // 启动Activity并等待结果
+ this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE);
+}
- sendBroadcast(intent);
- setResult(RESULT_OK, intent);
+// 打开文件夹
+private void openFolder(NoteItemData data) {
+ // 更新当前文件夹ID
+ mCurrentFolderId = data.getId();
+ // 重新查询笔记列表
+ startAsyncNotesListQuery();
+ if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
+ // 如果是通话记录文件夹,更新状态和UI
+ mState = ListEditState.CALL_RECORD_FOLDER;
+ mAddNewNote.setVisibility(View.GONE);
+ } else {
+ // 如果是普通文件夹,更新状态
+ mState = ListEditState.SUB_FOLDER;
}
- /**
- * 为文件夹创建上下文菜单的监听器
- */
- private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener() {
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- if (mFocusNoteDataItem != null) {
- menu.setHeaderTitle(mFocusNoteDataItem.getSnippet());
- menu.add(0, MENU_FOLDER_VIEW, 0, R.string.menu_folder_view);
- menu.add(0, MENU_FOLDER_DELETE, 0, R.string.menu_folder_delete);
- menu.add(0, MENU_FOLDER_CHANGE_NAME, 0, R.string.menu_folder_change_name);
- }
- }
- };
+ // 更新标题栏文本
+ if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
+ mTitleBar.setText(R.string.call_record_folder_name);
+ } else {
+ mTitleBar.setText(data.getSnippet());
+ }
+ // 显示标题栏
+ mTitleBar.setVisibility(View.VISIBLE);
+}
- @Override
- public void onContextMenuClosed(Menu menu) {
- if (mNotesListView != null) {
- mNotesListView.setOnCreateContextMenuListener(null);
- }
- super.onContextMenuClosed(menu);
+// 点击事件处理
+public void onClick(View v) {
+ // 根据点击的视图ID进行处理
+ switch (v.getId()) {
+ case R.id.btn_new_note:
+ // 创建新笔记
+ createNewNote();
+ break;
+ default:
+ // 其他按钮不做处理
+ break;
}
+}
+// 显示软键盘
+private void showSoftInput() {
+ // 获取InputMethodManager服务
+ InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (inputMethodManager != null) {
+ // 强制显示软键盘
+ inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
+ }
+}
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- if (mFocusNoteDataItem == null) {
+// 隐藏软键盘
+private void hideSoftInput(View view) {
+ // 获取InputMethodManager服务
+ InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ // 隐藏软键盘
+ inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
+}
+
+// 显示创建或修改文件夹对话框
+private void showCreateOrModifyFolderDialog(final boolean create) {
+ // 创建AlertDialog.Builder实例
+ final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ // 从布局文件中加载对话框视图
+ View view = LayoutInflater.from(this).inflate(R.layout.dialog_edit_text, null);
+ // 获取编辑文本框
+ final EditText etName = (EditText) view.findViewById(R.id.et_foler_name);
+ // 显示软键盘
+ showSoftInput();
+ if (!create) {
+ // 如果是修改文件夹
+ if (mFocusNoteDataItem != null) {
+ // 设置编辑文本框的初始值为当前文件夹名称
+ etName.setText(mFocusNoteDataItem.getSnippet());
+ // 设置对话框标题为“修改文件夹名称”
+ builder.setTitle(getString(R.string.menu_folder_change_name));
+ } else {
+ // 如果当前焦点笔记项为空,记录错误信息并返回
Log.e(TAG, "The long click data item is null");
- return false;
- }
- switch (item.getItemId()) {
- case MENU_FOLDER_VIEW:
- openFolder(mFocusNoteDataItem);
- break;
- case MENU_FOLDER_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_folder));
- builder.setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- deleteFolder(mFocusNoteDataItem.getId());
- }
- });
- builder.setNegativeButton(android.R.string.cancel, null);
- builder.show();
- break;
- case MENU_FOLDER_CHANGE_NAME:
- showCreateOrModifyFolderDialog(false);
- break;
- default:
- break;
+ return;
}
-
- return true;
+ } else {
+ // 如果是创建文件夹,清空编辑文本框
+ etName.setText("");
+ // 设置对话框标题为“创建文件夹”
+ builder.setTitle(this.getString(R.string.menu_create_folder));
}
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- menu.clear();
- if (mState == ListEditState.NOTE_LIST) {
- getMenuInflater().inflate(R.menu.note_list, menu);
- // 设置同步或取消同步的菜单项标题
- menu.findItem(R.id.menu_sync).setTitle(
- GTaskSyncService.isSyncing() ? R.string.menu_sync_cancel : R.string.menu_sync);
- } else if (mState == ListEditState.SUB_FOLDER) {
- getMenuInflater().inflate(R.menu.sub_folder, menu);
- } else if (mState == ListEditState.CALL_RECORD_FOLDER) {
- getMenuInflater().inflate(R.menu.call_record_folder, menu);
- } else {
- Log.e(TAG, "Wrong state:" + mState);
+ // 设置确认按钮,但不立即设置点击事件监听器
+ builder.setPositiveButton(android.R.string.ok, null);
+ // 设置取消按钮的点击事件监听器
+ builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // 隐藏软键盘
+ hideSoftInput(etName);
}
- return true;
- }
+ });
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.menu_new_folder: {
- showCreateOrModifyFolderDialog(true);
- break;
- }
- case R.id.menu_export_text: {
- exportNoteToText();
- break;
+ // 显示对话框
+ final Dialog dialog = builder.setView(view).show();
+ // 获取确认按钮
+ final Button positive = (Button) dialog.findViewById(android.R.id.button1);
+ // 设置确认按钮的点击事件监听器
+ positive.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ // 隐藏软键盘
+ hideSoftInput(etName);
+ // 获取编辑文本框的内容
+ String name = etName.getText().toString();
+ // 检查文件夹名称是否已存在
+ if (DataUtils.checkVisibleFolderName(mContentResolver, name)) {
+ // 如果文件夹名称已存在,显示提示信息
+ Toast.makeText(NotesListActivity.this, getString(R.string.folder_exist, name),
+ Toast.LENGTH_LONG).show();
+ // 选中编辑文本框的全部内容
+ etName.setSelection(0, etName.length());
+ return;
}
- case R.id.menu_sync: {
- if (isSyncMode()) {
- if (TextUtils.equals(item.getTitle(), getString(R.string.menu_sync))) {
- GTaskSyncService.startSync(this);
- } else {
- GTaskSyncService.cancelSync(this);
- }
- } else {
- startPreferenceActivity();
+ // 如果是修改文件夹
+ if (!create) {
+ if (!TextUtils.isEmpty(name)) {
+ // 创建ContentValues对象,设置文件夹名称和类型
+ ContentValues values = new ContentValues();
+ values.put(NoteColumns.SNIPPET, name);
+ values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
+ values.put(NoteColumns.LOCAL_MODIFIED, 1);
+ // 更新文件夹信息
+ mContentResolver.update(Notes.CONTENT_NOTE_URI, values, NoteColumns.ID
+ + "=?", new String[] {
+ String.valueOf(mFocusNoteDataItem.getId())
+ });
}
- break;
- }
- case R.id.menu_setting: {
- startPreferenceActivity();
- break;
+ } else if (!TextUtils.isEmpty(name)) {
+ // 如果是创建文件夹
+ ContentValues values = new ContentValues();
+ values.put(NoteColumns.SNIPPET, name);
+ values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
+ // 插入新文件夹
+ mContentResolver.insert(Notes.CONTENT_NOTE_URI, values);
}
- case R.id.menu_new_note: {
- createNewNote();
- break;
- }
- case R.id.menu_search:
- onSearchRequested();
- break;
- default:
- break;
+ // 关闭对话框
+ dialog.dismiss();
}
- return true;
- }
+ });
- @Override
- public boolean onSearchRequested() {
- startSearch(null, false, null /* appData */, false);
- return true;
+ // 如果编辑文本框为空,禁用确认按钮
+ if (TextUtils.isEmpty(etName.getText())) {
+ positive.setEnabled(false);
}
-
/**
- * 导出笔记到文本文件的函数
+ * 当编辑文本框为空时,禁用确认按钮
*/
- private void exportNoteToText() {
- final BackupUtils backup = BackupUtils.getInstance(NotesListActivity.this);
- new AsyncTask() {
+ etName.addTextChangedListener(new TextWatcher() {
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // 文本变化前的处理
+ }
- @Override
- protected Integer doInBackground(Void... unused) {
- return backup.exportToText();
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // 文本变化时的处理
+ if (TextUtils.isEmpty(etName.getText())) {
+ // 如果编辑文本框为空,禁用确认按钮
+ positive.setEnabled(false);
+ } else {
+ // 如果编辑文本框不为空,启用确认按钮
+ positive.setEnabled(true);
}
+ }
- @Override
- protected void onPostExecute(Integer result) {
- if (result == BackupUtils.STATE_SD_CARD_UNMOUONTED) {
- AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
- builder.setTitle(NotesListActivity.this
- .getString(R.string.failed_sdcard_export));
- builder.setMessage(NotesListActivity.this
- .getString(R.string.error_sdcard_unmounted));
- builder.setPositiveButton(android.R.string.ok, null);
- builder.show();
- } else if (result == BackupUtils.STATE_SUCCESS) {
- AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
- builder.setTitle(NotesListActivity.this
- .getString(R.string.success_sdcard_export));
- builder.setMessage(NotesListActivity.this.getString(
- R.string.format_exported_file_location, backup
- .getExportedTextFileName(), backup.getExportedTextFileDir()));
- builder.setPositiveButton(android.R.string.ok, null);
- builder.show();
- } else if (result == BackupUtils.STATE_SYSTEM_ERROR) {
- AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
- builder.setTitle(NotesListActivity.this
- .getString(R.string.failed_sdcard_export));
- builder.setMessage(NotesListActivity.this
- .getString(R.string.error_sdcard_export));
- builder.setPositiveButton(android.R.string.ok, null);
- builder.show();
- }
- }
+ public void afterTextChanged(Editable s) {
+ // 文本变化后的处理
+ }
+ });
+}@Override
+public void onBackPressed() {
+ // 根据当前状态处理返回键事件
+ switch (mState) {
+ case SUB_FOLDER:
+ // 如果当前在子文件夹状态,返回根文件夹
+ mCurrentFolderId = Notes.ID_ROOT_FOLDER;
+ mState = ListEditState.NOTE_LIST;
+ startAsyncNotesListQuery();
+ mTitleBar.setVisibility(View.GONE);
+ break;
+ case CALL_RECORD_FOLDER:
+ // 如果当前在通话记录文件夹状态,返回根文件夹
+ mCurrentFolderId = Notes.ID_ROOT_FOLDER;
+ mState = ListEditState.NOTE_LIST;
+ mAddNewNote.setVisibility(View.VISIBLE);
+ mTitleBar.setVisibility(View.GONE);
+ startAsyncNotesListQuery();
+ break;
+ case NOTE_LIST:
+ // 如果当前在笔记列表状态,调用父类的onBackPressed方法
+ super.onBackPressed();
+ break;
+ default:
+ // 其他状态不做处理
+ break;
+ }
+}
- }.execute();
+// 更新小部件
+private void updateWidget(int appWidgetId, int appWidgetType) {
+ // 创建更新小部件的Intent
+ Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
+ // 根据小部件类型设置对应的Provider
+ if (appWidgetType == Notes.TYPE_WIDGET_2X) {
+ intent.setClass(this, NoteWidgetProvider_2x.class);
+ } else if (appWidgetType == Notes.TYPE_WIDGET_4X) {
+ intent.setClass(this, NoteWidgetProvider_4x.class);
+ } else {
+ // 如果小部件类型不支持,记录错误信息并返回
+ Log.e(TAG, "Unsupported widget type");
+ return;
}
- /**
- * 检查是否处于同步模式的函数
- */
- private boolean isSyncMode() {
- return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
+ // 传递小部件ID
+ intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
+ appWidgetId
+ });
+
+ // 发送广播更新小部件
+ sendBroadcast(intent);
+ // 设置结果为成功
+ setResult(RESULT_OK, intent);
+}
+
+// 文件夹长按事件的上下文菜单创建监听器
+private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener() {
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+ // 如果当前焦点笔记项不为空
+ if (mFocusNoteDataItem != null) {
+ // 设置菜单标题为文件夹名称
+ menu.setHeaderTitle(mFocusNoteDataItem.getSnippet());
+ // 添加查看文件夹菜单项
+ menu.add(0, MENU_FOLDER_VIEW, 0, R.string.menu_folder_view);
+ // 添加删除文件夹菜单项
+ menu.add(0, MENU_FOLDER_DELETE, 0, R.string.menu_folder_delete);
+ // 添加修改文件夹名称菜单项
+ menu.add(0, MENU_FOLDER_CHANGE_NAME, 0, R.string.menu_folder_change_name);
+ }
}
+};
- /**
- * 启动偏好设置活动的函数
- */
- private void startPreferenceActivity() {
- Activity from = getParent() != null ? getParent() : this;
- Intent intent = new Intent(from, NotesPreferenceActivity.class);
- from.startActivityIfNeeded(intent, -1);
+// 上下文菜单关闭时调用
+@Override
+public void onContextMenuClosed(Menu menu) {
+ // 移除列表视图的上下文菜单创建监听器
+ if (mNotesListView != null) {
+ mNotesListView.setOnCreateContextMenuListener(null);
}
+ // 调用父类的onContextMenuClosed方法
+ super.onContextMenuClosed(menu);
+}
- // 列表项点击事件的监听器
- private class OnListItemClickListener implements OnItemClickListener {
+// 上下文菜单项点击事件处理
+@Override
+public boolean onContextItemSelected(MenuItem item) {
+ // 如果当前焦点笔记项为空,记录错误信息并返回false
+ if (mFocusNoteDataItem == null) {
+ Log.e(TAG, "The long click data item is null");
+ return false;
+ }
+ // 根据菜单项ID进行处理
+ switch (item.getItemId()) {
+ case MENU_FOLDER_VIEW:
+ // 查看文件夹
+ openFolder(mFocusNoteDataItem);
+ break;
+ case MENU_FOLDER_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_folder));
+ builder.setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ deleteFolder(mFocusNoteDataItem.getId());
+ }
+ });
+ builder.setNegativeButton(android.R.string.cancel, null);
+ builder.show();
+ break;
+ case MENU_FOLDER_CHANGE_NAME:
+ // 修改文件夹名称
+ showCreateOrModifyFolderDialog(false);
+ break;
+ default:
+ // 其他菜单项不做处理
+ break;
+ }
+ // 处理成功,返回true
+ return true;
+}
- public void onItemClick(AdapterView> parent, View view, int position, long id) {
- if (view instanceof NotesListItem) {
- NoteItemData item = ((NotesListItem) view).getItemData();
- if (mNotesListAdapter.isInChoiceMode()) {
- if (item.getType() == Notes.TYPE_NOTE) {
- position = position - mNotesListView.getHeaderViewsCount();
- mModeCallBack.onItemCheckedStateChanged(null, position, id,
- !mNotesListAdapter.isSelectedItem(position));
- }
- return;
- }
+// 准备选项菜单时调用
+@Override
+public boolean onPrepareOptionsMenu(Menu menu) {
+ // 清空当前菜单
+ menu.clear();
+ // 根据当前状态加载对应的菜单资源
+ if (mState == ListEditState.NOTE_LIST) {
+ getMenuInflater().inflate(R.menu.note_list, menu);
+ // 设置同步或取消同步的菜单项标题
+ menu.findItem(R.id.menu_sync).setTitle(
+ GTaskSyncService.isSyncing() ? R.string.menu_sync_cancel : R.string.menu_sync);
+ } else if (mState == ListEditState.SUB_FOLDER) {
+ getMenuInflater().inflate(R.menu.sub_folder, menu);
+ } else if (mState == ListEditState.CALL_RECORD_FOLDER) {
+ getMenuInflater().inflate(R.menu.call_record_folder, menu);
+ } else {
+ // 如果状态未知,记录错误信息
+ Log.e(TAG, "Wrong state:" + mState);
+ }
+ // 返回true表示菜单已准备
+ return true;
+}
- switch (mState) {
- case NOTE_LIST:
- if (item.getType() == Notes.TYPE_FOLDER
- || item.getType() == Notes.TYPE_SYSTEM) {
- openFolder(item);
- } else if (item.getType() == Notes.TYPE_NOTE) {
- openNode(item);
- } else {
- Log.e(TAG, "Wrong note type in NOTE_LIST");
- }
- break;
- case SUB_FOLDER:
- case CALL_RECORD_FOLDER:
- if (item.getType() == Notes.TYPE_NOTE) {
- openNode(item);
- } else {
- Log.e(TAG, "Wrong note type in SUB_FOLDER");
- }
- break;
- default:
- break;
+// 选项菜单项点击事件处理
+@Override
+public boolean onOptionsItemSelected(MenuItem item) {
+ // 根据菜单项ID进行处理
+ switch (item.getItemId()) {
+ case R.id.menu_new_folder:
+ // 创建新文件夹
+ showCreateOrModifyFolderDialog(true);
+ break;
+ case R.id.menu_export_text:
+ // 导出笔记到文本文件
+ exportNoteToText();
+ break;
+ case R.id.menu_sync:
+ // 处理同步或取消同步
+ if (isSyncMode()) {
+ if (TextUtils.equals(item.getTitle(), getString(R.string.menu_sync))) {
+ GTaskSyncService.startSync(this);
+ } else {
+ GTaskSyncService.cancelSync(this);
}
+ } else {
+ startPreferenceActivity();
}
+ break;
+ case R.id.menu_setting:
+ // 打开设置活动
+ startPreferenceActivity();
+ break;
+ case R.id.menu_new_note:
+ // 创建新笔记
+ createNewNote();
+ break;
+ case R.id.menu_search:
+ // 请求搜索
+ onSearchRequested();
+ break;
+ default:
+ // 其他菜单项不做处理
+ break;
+ }
+ // 处理成功,返回true
+ return true;
+}
+// 搜索请求处理
+@Override
+public boolean onSearchRequested() {
+ // 启动搜索,不传递额外数据
+ startSearch(null, false, null /* appData */, false);
+ // 返回true表示已处理搜索请求
+ return true;
+}
+
+// 导出笔记到文本文件
+private void exportNoteToText() {
+ // 获取BackupUtils实例
+ final BackupUtils backup = BackupUtils.getInstance(NotesListActivity.this);
+ // 创建异步任务
+ new AsyncTask() {
+ @Override
+ protected Integer doInBackground(Void... unused) {
+ // 执行导出操作
+ return backup.exportToText();
}
- }
+ @Override
+ protected void onPostExecute(Integer result) {
+ // 根据导出结果处理
+ if (result == BackupUtils.STATE_SD_CARD_UNMOUONTED) {
+ // 如果SD卡未挂载,显示错误提示
+ AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
+ builder.setTitle(NotesListActivity.this.getString(R.string.failed_sdcard_export));
+ builder.setMessage(NotesListActivity.this.getString(R.string.error_sdcard_unmounted));
+ builder.setPositiveButton(android.R.string.ok, null);
+ builder.show();
+ } else if (result == BackupUtils.STATE_SUCCESS) {
+ // 如果导出成功,显示成功提示
+ AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
+ builder.setTitle(NotesListActivity.this.getString(R.string.success_sdcard_export));
+ builder.setMessage(NotesListActivity.this.getString(
+ R.string.format_exported_file_location,
+ backup.getExportedTextFileName(),
+ backup.getExportedTextFileDir()));
+ builder.setPositiveButton(android.R.string.ok, null);
+ builder.show();
+ } else if (result == BackupUtils.STATE_SYSTEM_ERROR) {
+ // 如果发生系统错误,显示错误提示
+ AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
+ builder.setTitle(NotesListActivity.this.getString(R.string.failed_sdcard_export));
+ builder.setMessage(NotesListActivity.this.getString(R.string.error_sdcard_export));
+ builder.setPositiveButton(android.R.string.ok, null);
+ builder.show();
+ }
+ }
+ }.execute();
+}
- /**
- * 开始查询目标文件夹的函数
- */
- private void startQueryDestinationFolders() {
- String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>? AND " + NoteColumns.ID + "<>?";
- selection = (mState == ListEditState.NOTE_LIST) ? selection:
- "(" + selection + ") OR (" + NoteColumns.ID + "=" + Notes.ID_ROOT_FOLDER + ")";
+// 检查是否处于同步模式
+private boolean isSyncMode() {
+ // 获取同步账户名称,如果非空则表示处于同步模式
+ return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
+}
- mBackgroundQueryHandler.startQuery(FOLDER_LIST_QUERY_TOKEN,
- null,
- Notes.CONTENT_NOTE_URI,
- FoldersListAdapter.PROJECTION,
- selection,
- new String[] {
- String.valueOf(Notes.TYPE_FOLDER),
- String.valueOf(Notes.ID_TRASH_FOLER),
- String.valueOf(mCurrentFolderId)
- },
- NoteColumns.MODIFIED_DATE + " DESC");
- }
+// 启动偏好设置活动
+private void startPreferenceActivity() {
+ // 获取当前Activity或其父Activity
+ Activity from = getParent() != null ? getParent() : this;
+ // 创建启动偏好设置活动的Intent
+ Intent intent = new Intent(from, NotesPreferenceActivity.class);
+ // 启动活动
+ from.startActivityIfNeeded(intent, -1);
+}
- @Override
- public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
+// 列表项点击事件监听器
+private class OnListItemClickListener implements OnItemClickListener {
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
if (view instanceof NotesListItem) {
- mFocusNoteDataItem = ((NotesListItem) view).getItemData();
- if (mFocusNoteDataItem.getType() == Notes.TYPE_NOTE && !mNotesListAdapter.isInChoiceMode()) {
- if (mNotesListView.startActionMode(mModeCallBack) != null) {
- mModeCallBack.onItemCheckedStateChanged(null, position, id, true);
- mNotesListView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- } else {
- Log.e(TAG, "startActionMode fails");
+ // 获取点击的笔记项数据
+ NoteItemData item = ((NotesListItem) view).getItemData();
+ if (mNotesListAdapter.isInChoiceMode()) {
+ // 如果处于选择模式
+ if (item.getType() == Notes.TYPE_NOTE) {
+ // 调整位置,排除头部视图
+ position = position - mNotesListView.getHeaderViewsCount();
+ // 切换选中状态
+ mModeCallBack.onItemCheckedStateChanged(null, position, id,
+ !mNotesListAdapter.isSelectedItem(position));
}
- } else if (mFocusNoteDataItem.getType() == Notes.TYPE_FOLDER) {
- mNotesListView.setOnCreateContextMenuListener(mFolderOnCreateContextMenuListener);
+ return;
+ }
+
+ // 根据当前状态和笔记类型处理点击事件
+ switch (mState) {
+ case NOTE_LIST:
+ if (item.getType() == Notes.TYPE_FOLDER || item.getType() == Notes.TYPE_SYSTEM) {
+ // 打开文件夹
+ openFolder(item);
+ } else if (item.getType() == Notes.TYPE_NOTE) {
+ // 打开笔记
+ openNode(item);
+ } else {
+ // 记录错误信息
+ Log.e(TAG, "Wrong note type in NOTE_LIST");
+ }
+ break;
+ case SUB_FOLDER:
+ case CALL_RECORD_FOLDER:
+ if (item.getType() == Notes.TYPE_NOTE) {
+ // 打开笔记
+ openNode(item);
+ } else {
+ // 记录错误信息
+ Log.e(TAG, "Wrong note type in SUB_FOLDER");
+ }
+ break;
+ default:
+ // 其他状态不做处理
+ break;
}
}
- return false;
}
}
-
\ No newline at end of file
+// 启动查询目标文件夹
+private void startQueryDestinationFolders() {
+ // 构建查询条件
+ String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>? AND " + NoteColumns.ID + "<>?";
+ selection = (mState == ListEditState.NOTE_LIST) ? selection :
+ "(" + selection + ") OR (" + NoteColumns.ID + "=" + Notes.ID_ROOT_FOLDER + ")";
+
+ // 启动异步查询
+ mBackgroundQueryHandler.startQuery(FOLDER_LIST_QUERY_TOKEN,
+ null,
+ Notes.CONTENT_NOTE_URI,
+ FoldersListAdapter.PROJECTION,
+ selection,
+ new String[] {
+ String.valueOf(Notes.TYPE_FOLDER),
+ String.valueOf(Notes.ID_TRASH_FOLER),
+ String.valueOf(mCurrentFolderId)
+ },
+ NoteColumns.MODIFIED_DATE + " DESC");
+}
+
+// 列表项长按事件处理
+public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
+ if (view instanceof NotesListItem) {
+ // 获取长按的笔记项数据
+ mFocusNoteDataItem = ((NotesListItem) view).getItemData();
+ if (mFocusNoteDataItem.getType() == Notes.TYPE_NOTE && !mNotesListAdapter.isInChoiceMode()) {
+ // 如果是笔记且不在选择模式,启动多选模式
+ if (mNotesListView.startActionMode(mModeCallBack) != null) {
+ // 切换选中状态
+ mModeCallBack.onItemCheckedStateChanged(null, position, id, true);
+ // 触发长按反馈
+ mNotesListView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ } else {
+ // 记录错误信息
+ Log.e(TAG, "startActionMode fails");
+ }
+ } else if (mFocusNoteDataItem.getType() == Notes.TYPE_FOLDER) {
+ // 如果是文件夹,设置上下文菜单监听器
+ mNotesListView.setOnCreateContextMenuListener(mFolderOnCreateContextMenuListener);
+ }
+ }
+ // 返回false表示事件已处理
+ return false;
+}
\ No newline at end of file
diff --git a/src/ui(m)/NotesPreferenceActivity.java b/src/ui(m)/NotesPreferenceActivity.java
index 7a59d05..a594b98 100644
--- a/src/ui(m)/NotesPreferenceActivity.java
+++ b/src/ui(m)/NotesPreferenceActivity.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+// 导入所需的包,这些包提供了各种 Android 开发中常用的类和接口
package net.micode.notes.ui;
import android.accounts.Account;
@@ -47,74 +48,90 @@ import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.remote.GTaskSyncService;
-/**
- * 设置和偏好活动,用于配置应用程序的偏好设置。
- */
+// 定义一个名为 NotesPreferenceActivity 的类,继承自 PreferenceActivity,用于处理应用的偏好设置相关操作
public class NotesPreferenceActivity extends PreferenceActivity {
- // 偏好设置文件的名称
+ // 定义一个常量,表示偏好设置的名称
public static final String PREFERENCE_NAME = "notes_preferences";
- // 同步账户名称的键
+
+ // 定义常量,表示同步账户名称的偏好设置键
public static final String PREFERENCE_SYNC_ACCOUNT_NAME = "pref_key_account_name";
- // 最后一次同步时间的键
+
+ // 定义常量,表示最后一次同步时间的偏好设置键
public static final String PREFERENCE_LAST_SYNC_TIME = "pref_last_sync_time";
- // 设置背景颜色的键
+
+ // 定义常量,表示设置背景颜色的偏好设置键
public static final String PREFERENCE_SET_BG_COLOR_KEY = "pref_key_bg_random_appear";
- // 同步账户的键
+
+ // 定义常量,表示同步账户的偏好设置键
private static final String PREFERENCE_SYNC_ACCOUNT_KEY = "pref_sync_account_key";
- // 权限过滤键
+
+ // 定义常量,表示过滤器的键
private static final String AUTHORITIES_FILTER_KEY = "authorities";
- // 账户类别
+
+ // 声明一个 PreferenceCategory 类型的成员变量,用于存储账户相关的偏好设置分类
private PreferenceCategory mAccountCategory;
- // GTask接收器
+
+ // 声明一个 GTaskReceiver 类型的成员变量,用于接收与 GTask 相关的广播
private GTaskReceiver mReceiver;
- // 原始账户数组
+
+ // 声明一个 Account 数组类型的成员变量,用于存储原始账户信息
private Account[] mOriAccounts;
- // 是否添加了账户
+
+ // 声明一个布尔类型的成员变量,用于标记是否添加了新账户
private boolean mHasAddedAccount;
+ // 重写 onCreate 方法,用于初始化活动
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
- /* 使用应用程序图标进行导航 */
+ // 使用应用图标作为导航图标
getActionBar().setDisplayHomeAsUpEnabled(true);
// 从资源文件中添加偏好设置
addPreferencesFromResource(R.xml.preferences);
- // 获取账户类别
+ // 获取同步账户的偏好设置分类
mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY);
- // 创建GTask接收器
+ // 初始化 GTaskReceiver 实例
mReceiver = new GTaskReceiver();
- // 创建意图过滤器
+ // 创建 IntentFilter 实例,用于过滤与 GTask 服务相关的广播
IntentFilter filter = new IntentFilter();
filter.addAction(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME);
- // 注册接收器
+ // 注册广播接收器
registerReceiver(mReceiver, filter);
- // 初始化原始账户数组
+ // 初始化原始账户信息为 null
mOriAccounts = null;
- // 从XML布局文件中加载设置头部
+ // 使用布局填充器从布局文件中加载设置头部视图
View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null);
- // 将头部添加到偏好列表中
+ // 将头部视图添加到列表视图中
getListView().addHeaderView(header, null, true);
}
+ // 重写 onResume 方法,用于在活动恢复时执行相关操作
@Override
protected void onResume() {
super.onResume();
- // 自动设置同步账户,如果用户添加了新账户
+ // 如果添加了新账户,则需要自动设置同步账户
if (mHasAddedAccount) {
+ // 获取谷歌账户信息
Account[] accounts = getGoogleAccounts();
+ // 如果原始账户信息不为空且新获取的账户数量大于原始账户数量
if (mOriAccounts != null && accounts.length > mOriAccounts.length) {
+ // 遍历新获取的账户信息
for (Account accountNew : accounts) {
+ // 标记是否找到匹配的账户
boolean found = false;
+ // 遍历原始账户信息
for (Account accountOld : mOriAccounts) {
+ // 如果新旧账户名称相同,则标记为找到
if (TextUtils.equals(accountOld.name, accountNew.name)) {
found = true;
break;
}
}
+ // 如果未找到匹配的账户,则设置同步账户为新账户
if (!found) {
setSyncAccount(accountNew.name);
break;
@@ -123,172 +140,173 @@ public class NotesPreferenceActivity extends PreferenceActivity {
}
}
- // 刷新UI
+ // 刷新 UI 界面
refreshUI();
}
-
- @Override
- protected void onDestroy() {
- // 如果接收器不为空,注销接收器
- if (mReceiver != null) {
- unregisterReceiver(mReceiver);
- }
- super.onDestroy();
+// 重写 onDestroy 方法,用于在活动销毁时执行相关操作
+@Override
+protected void onDestroy() {
+ // 如果广播接收器不为空,则注销广播接收器
+ if (mReceiver != null) {
+ unregisterReceiver(mReceiver);
}
+ // 调用父类的 onDestroy 方法
+ super.onDestroy();
+}
- /**
- * 加载账户偏好设置。
- */
- private void loadAccountPreference() {
- // 移除所有账户偏好设置
- mAccountCategory.removeAll();
-
- // 创建一个新的偏好设置
- Preference accountPref = new Preference(this);
- // 获取默认账户
- final String defaultAccount = getSyncAccountName(this);
- accountPref.setTitle(getString(R.string.preferences_account_title));
- accountPref.setSummary(getString(R.string.preferences_account_summary));
- accountPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- public boolean onPreferenceClick(Preference preference) {
- // 如果GTask服务没有正在同步
- if (!GTaskSyncService.isSyncing()) {
- // 如果默认账户为空
- if (TextUtils.isEmpty(defaultAccount)) {
- // 第一次设置账户
- showSelectAccountAlertDialog();
- } else {
- // 如果账户已经设置,提示用户风险
- showChangeAccountConfirmAlertDialog();
- }
+// 定义一个私有方法 loadAccountPreference,用于加载账户相关的偏好设置
+private void loadAccountPreference() {
+ // 清除账户分类中的所有偏好设置
+ mAccountCategory.removeAll();
+
+ // 创建一个新的 Preference 实例
+ Preference accountPref = new Preference(this);
+ // 获取默认的同步账户名称
+ final String defaultAccount = getSyncAccountName(this);
+ // 设置偏好设置的标题
+ accountPref.setTitle(getString(R.string.preferences_account_title));
+ // 设置偏好设置的摘要
+ accountPref.setSummary(getString(R.string.preferences_account_summary));
+ // 设置偏好设置的点击监听器
+ accountPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ public boolean onPreferenceClick(Preference preference) {
+ // 如果没有正在同步
+ if (!GTaskSyncService.isSyncing()) {
+ // 如果默认账户名称为空
+ if (TextUtils.isEmpty(defaultAccount)) {
+ // 显示选择账户的对话框
+ showSelectAccountAlertDialog();
} else {
- // 提示用户不能更改账户
- Toast.makeText(NotesPreferenceActivity.this,
- R.string.preferences_toast_cannot_change_account, Toast.LENGTH_SHORT)
- .show();
+ // 如果账户已经设置,提示用户更改账户的风险
+ showChangeAccountConfirmAlertDialog();
}
- return true;
+ } else {
+ // 显示提示信息,表示不能更改账户
+ Toast.makeText(NotesPreferenceActivity.this,
+ R.string.preferences_toast_cannot_change_account, Toast.LENGTH_SHORT)
+ .show();
}
- });
-
- // 将账户偏好设置添加到账户类别中
- mAccountCategory.addPreference(accountPref);
- }
-
- /**
- * 加载同步按钮。
- */
- private void loadSyncButton() {
- // 获取同步按钮和最后同步时间视图
- Button syncButton = (Button) findViewById(R.id.preference_sync_button);
- TextView lastSyncTimeView = (TextView) findViewById(R.id.prefenerece_sync_status_textview);
-
- // 设置按钮状态
- if (GTaskSyncService.isSyncing()) {
- syncButton.setText(getString(R.string.preferences_button_sync_cancel));
- syncButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- // 取消同步
- GTaskSyncService.cancelSync(NotesPreferenceActivity.this);
- }
- });
- } else {
- syncButton.setText(getString(R.string.preferences_button_sync_immediately));
- syncButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- // 立即同步
- GTaskSyncService.startSync(NotesPreferenceActivity.this);
- }
- });
+ return true;
}
- syncButton.setEnabled(!TextUtils.isEmpty(getSyncAccountName(this)));
+ });
+
+ // 将账户偏好设置添加到账户分类中
+ mAccountCategory.addPreference(accountPref);
+}
- // 设置最后同步时间
- if (GTaskSyncService.isSyncing()) {
- lastSyncTimeView.setText(GTaskSyncService.getProgressString());
+// 定义一个私有方法 loadSyncButton,用于加载同步按钮和显示最后一次同步时间
+private void loadSyncButton() {
+ // 获取同步按钮和显示最后一次同步时间的文本视图
+ Button syncButton = (Button) findViewById(R.id.preference_sync_button);
+ TextView lastSyncTimeView = (TextView) findViewById(R.id.prefenerece_sync_status_textview);
+
+ // 设置按钮状态
+ if (GTaskSyncService.isSyncing()) {
+ // 如果正在同步,设置按钮文本为取消同步,并设置点击监听器
+ syncButton.setText(getString(R.string.preferences_button_sync_cancel));
+ syncButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ GTaskSyncService.cancelSync(NotesPreferenceActivity.this);
+ }
+ });
+ } else {
+ // 如果没有正在同步,设置按钮文本为立即同步,并设置点击监听器
+ syncButton.setText(getString(R.string.preferences_button_sync_immediately));
+ syncButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ GTaskSyncService.startSync(NotesPreferenceActivity.this);
+ }
+ });
+ }
+ // 如果同步账户名称不为空,启用按钮
+ syncButton.setEnabled(!TextUtils.isEmpty(getSyncAccountName(this)));
+
+ // 设置最后一次同步时间
+ if (GTaskSyncService.isSyncing()) {
+ // 如果正在同步,显示同步进度
+ lastSyncTimeView.setText(GTaskSyncService.getProgressString());
+ lastSyncTimeView.setVisibility(View.VISIBLE);
+ } else {
+ // 如果没有正在同步,显示最后一次同步时间
+ long lastSyncTime = getLastSyncTime(this);
+ if (lastSyncTime != 0) {
+ lastSyncTimeView.setText(getString(R.string.preferences_last_sync_time,
+ DateFormat.format(getString(R.string.preferences_last_sync_time_format),
+ lastSyncTime)));
lastSyncTimeView.setVisibility(View.VISIBLE);
} else {
- long lastSyncTime = getLastSyncTime(this);
- if (lastSyncTime != 0) {
- lastSyncTimeView.setText(getString(R.string.preferences_last_sync_time,
- DateFormat.format(getString(R.string.preferences_last_sync_time_format),
- lastSyncTime)));
- lastSyncTimeView.setVisibility(View.VISIBLE);
- } else {
- lastSyncTimeView.setVisibility(View.GONE);
- }
+ lastSyncTimeView.setVisibility(View.GONE);
}
}
+}
- /**
- * 刷新UI。
- */
- private void refreshUI() {
- // 加载账户偏好设置和同步按钮
- loadAccountPreference();
- loadSyncButton();
- }
+// 定义一个私有方法 refreshUI,用于刷新 UI 界面
+private void refreshUI() {
+ // 加载账户偏好设置和同步按钮
+ loadAccountPreference();
+ loadSyncButton();
+}
- /**
- * 显示选择账户的警告对话框。
- */
- private void showSelectAccountAlertDialog() {
- // 创建警告对话框的构建器
- AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
-
- // 从XML布局文件中加载标题视图
- View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null);
- TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title);
- titleTextView.setText(getString(R.string.preferences_dialog_select_account_title));
- TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle);
- subtitleTextView.setText(getString(R.string.preferences_dialog_select_account_tips));
-
- // 设置自定义标题
- dialogBuilder.setCustomTitle(titleView);
- dialogBuilder.setPositiveButton(null, null);
-
- // 获取Google账户
- Account[] accounts = getGoogleAccounts());
- String defAccount = getSyncAccountName(this);
-
- // 初始化原始账户数组和添加账户标志
- mOriAccounts = accounts;
- mHasAddedAccount = false;
-
- // 如果账户数量大于0
- if (accounts.length > 0) {
- // 创建账户项
- CharSequence[] items = new CharSequence[accounts.length];
- final CharSequence[] itemMapping = items;
- int checkedItem = -1;
- int index = 0;
- for (Account account : accounts) {
- if (TextUtils.equals(account.name, defAccount)) {
- checkedItem = index;
- }
- items[index++] = account.name;
+// 定义一个私有方法 showSelectAccountAlertDialog,用于显示选择账户的对话框
+private void showSelectAccountAlertDialog() {
+ // 创建一个对话框构建器
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
+
+ // 从布局文件中加载自定义标题视图
+ View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null);
+ TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title);
+ titleTextView.setText(getString(R.string.preferences_dialog_select_account_title));
+ TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle);
+ subtitleTextView.setText(getString(R.string.preferences_dialog_select_account_tips));
+
+ // 设置自定义标题
+ dialogBuilder.setCustomTitle(titleView);
+ dialogBuilder.setPositiveButton(null, null);
+
+ // 获取谷歌账户信息
+ Account[] accounts = getGoogleAccounts();
+ String defAccount = getSyncAccountName(this);
+
+ // 保存原始账户信息
+ mOriAccounts = accounts;
+ mHasAddedAccount = false;
+
+ // 如果有账户信息
+ if (accounts.length > 0) {
+ // 创建账户名称数组
+ CharSequence[] items = new CharSequence[accounts.length];
+ final CharSequence[] itemMapping = items;
+ int checkedItem = -1;
+ int index = 0;
+ for (Account account : accounts) {
+ if (TextUtils.equals(account.name, defAccount)) {
+ checkedItem = index;
}
- // 设置单选项目
- dialogBuilder.setSingleChoiceItems(items, checkedItem,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- //设置同步账户
- setSyncAccount(itemMapping[which].toString());
- dialog.dismiss();
- refreshUI();
- }
- });
- }
- // 从XML布局文件中加载添加账户视图
+ items[index++] = account.name;
+ }
+ // 设置单选列表项
+ dialogBuilder.setSingleChoiceItems(items, checkedItem,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // 设置同步账户
+ setSyncAccount(itemMapping[which].toString());
+ dialog.dismiss();
+ refreshUI();
+ }
+ });
+ }
+
+ // 从布局文件中加载添加账户视图
View addAccountView = LayoutInflater.from(this).inflate(R.layout.add_account_text, null);
dialogBuilder.setView(addAccountView);
- // 显示警告对话框
+ // 显示对话框
final AlertDialog dialog = dialogBuilder.show();
addAccountView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
- // 添加账户
+ // 标记添加了新账户
mHasAddedAccount = true;
+ // 启动添加账户的设置活动
Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
intent.putExtra(AUTHORITIES_FILTER_KEY, new String[] {
"gmail-ls"
@@ -299,14 +317,12 @@ public class NotesPreferenceActivity extends PreferenceActivity {
});
}
-/**
- * 显示更改账户的确认警告对话框。
- */
+// 定义一个私有方法 showChangeAccountConfirmAlertDialog,用于显示更改账户确认对话框
private void showChangeAccountConfirmAlertDialog() {
- // 创建警告对话框的构建器
+ // 创建一个对话框构建器
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
- // 从XML布局文件中加载标题视图
+ // 从布局文件中加载自定义标题视图
View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null);
TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title);
titleTextView.setText(getString(R.string.preferences_dialog_change_account_title,
@@ -315,56 +331,57 @@ private void showChangeAccountConfirmAlertDialog() {
subtitleTextView.setText(getString(R.string.preferences_dialog_change_account_warn_msg));
dialogBuilder.setCustomTitle(titleView);
- // 创建菜单项
+ // 创建菜单项数组
CharSequence[] menuItemArray = new CharSequence[] {
getString(R.string.preferences_menu_change_account),
getString(R.string.preferences_menu_remove_account),
getString(R.string.preferences_menu_cancel)
};
+ // 设置菜单项点击监听器
dialogBuilder.setItems(menuItemArray, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
- // 处理菜单项点击事件
if (which == 0) {
+ // 显示选择账户的对话框
showSelectAccountAlertDialog();
} else if (which == 1) {
+ // 移除同步账户
removeSyncAccount();
refreshUI();
}
}
});
+ // 显示对话框
dialogBuilder.show();
}
-
-/**
- * 获取Google账户。
- */
+// 定义一个私有方法 getGoogleAccounts,用于获取谷歌账户信息
private Account[] getGoogleAccounts() {
- // 获取账户管理器
+ // 获取 AccountManager 实例
AccountManager accountManager = AccountManager.get(this);
- // 获取Google账户
+ // 返回类型为 "com.google" 的账户数组
return accountManager.getAccountsByType("com.google");
}
-/**
- * 设置同步账户。
- */
+// 定义一个私有方法 setSyncAccount,用于设置同步账户
private void setSyncAccount(String account) {
- // 如果同步账户不为空且与当前账户不同
+ // 如果新账户与当前设置的同步账户不同
if (!getSyncAccountName(this).equals(account)) {
- // 获取共享首选项
+ // 获取共享偏好设置
SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
+ // 获取编辑器
SharedPreferences.Editor editor = settings.edit();
+ // 如果账户不为空,则设置同步账户名称,否则设置为空字符串
if (account != null) {
editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, account);
} else {
editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
}
+ // 提交编辑
editor.commit();
- // 清除最后同步时间
+ // 清除最后一次同步时间
setLastSyncTime(this, 0);
- // 清除本地gtask相关信息
+ // 清除本地与 GTask 相关的信息
new Thread(new Runnable() {
public void run() {
ContentValues values = new ContentValues();
@@ -374,29 +391,31 @@ private void setSyncAccount(String account) {
}
}).start();
- // 提示用户设置账户成功
+ // 显示设置账户成功的提示信息
Toast.makeText(NotesPreferenceActivity.this,
getString(R.string.preferences_toast_success_set_accout, account),
Toast.LENGTH_SHORT).show();
}
}
-/**
- * 移除同步账户。
- */
+// 定义一个私有方法 removeSyncAccount,用于移除同步账户
private void removeSyncAccount() {
- // 获取共享首选项
+ // 获取共享偏好设置
SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
+ // 获取编辑器
SharedPreferences.Editor editor = settings.edit();
+ // 如果存在同步账户名称,则移除
if (settings.contains(PREFERENCE_SYNC_ACCOUNT_NAME)) {
editor.remove(PREFERENCE_SYNC_ACCOUNT_NAME);
}
+ // 如果存在最后一次同步时间,则移除
if (settings.contains(PREFERENCE_LAST_SYNC_TIME)) {
editor.remove(PREFERENCE_LAST_SYNC_TIME);
}
+ // 提交编辑
editor.commit();
- // 清除本地gtask相关信息
+ // 清除本地与 GTask 相关的信息
new Thread(new Runnable() {
public void run() {
ContentValues values = new ContentValues();
@@ -407,65 +426,69 @@ private void removeSyncAccount() {
}).start();
}
-/**
- * 获取同步账户名称。
- */
+// 定义一个公共静态方法 getSyncAccountName,用于获取同步账户名称
public static String getSyncAccountName(Context context) {
+ // 获取共享偏好设置
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
+ // 返回同步账户名称,如果不存在则返回空字符串
return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
}
-/**
- * 设置最后同步时间。
- */
+// 定义一个公共静态方法 setLastSyncTime,用于设置最后一次同步时间
public static void setLastSyncTime(Context context, long time) {
+ // 获取共享偏好设置
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
+ // 获取编辑器
SharedPreferences.Editor editor = settings.edit();
+ // 设置最后一次同步时间
editor.putLong(PREFERENCE_LAST_SYNC_TIME, time);
+ // 提交编辑
editor.commit();
}
-/**
- * 获取最后同步时间。
- */
+// 定义一个公共静态方法 getLastSyncTime,用于获取最后一次同步时间
public static long getLastSyncTime(Context context) {
+ // 获取共享偏好设置
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
+ // 返回最后一次同步时间,如果不存在则返回 0
return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0);
}
-/**
- * GTask接收器,用于接收GTask服务的广播。
- */
+// 定义一个内部类 GTaskReceiver,继承自 BroadcastReceiver,用于接收 GTask 相关的广播
private class GTaskReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- // 刷新UI
+ // 刷新 UI 界面
refreshUI();
+ // 如果正在同步
if (intent.getBooleanExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_IS_SYNCING, false)) {
- // 获取同步状态视图
+ // 获取显示同步状态的文本视图
TextView syncStatus = (TextView) findViewById(R.id.prefenerece_sync_status_textview);
+ // 设置同步状态文本
syncStatus.setText(intent
.getStringExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_PROGRESS_MSG));
}
-
}
}
-/**
- * 处理选项菜单项点击事件。
- */
+// 重写 onOptionsItemSelected 方法,用于处理菜单项点击事件
public boolean onOptionsItemSelected(MenuItem item) {
+ // 根据菜单项的 ID 进行处理
switch (item.getItemId()) {
case android.R.id.home:
+ // 创建一个 Intent,用于启动 NotesListActivity
Intent intent = new Intent(this, NotesListActivity.class);
+ // 添加标志,清除任务栈顶部的活动
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ // 启动活动
startActivity(intent);
return true;
default:
return false;
}
}
+