|
|
|
@ -77,65 +77,91 @@ import java.io.IOException;
|
|
|
|
|
import java.io.InputStream;
|
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
|
|
|
|
|
//这个类实现了一个便签列表的界面,并包含了点击事件和长按事件的处理。
|
|
|
|
|
public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener {
|
|
|
|
|
// 定义查询便签列表的令牌
|
|
|
|
|
private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0;
|
|
|
|
|
|
|
|
|
|
private static final int FOLDER_LIST_QUERY_TOKEN = 1;
|
|
|
|
|
// 定义查询文件夹列表的令牌
|
|
|
|
|
private static final int FOLDER_LIST_QUERY_TOKEN = 1;
|
|
|
|
|
|
|
|
|
|
// 定义文件夹菜单选项的常量
|
|
|
|
|
private static final int MENU_FOLDER_DELETE = 0;
|
|
|
|
|
|
|
|
|
|
private static final int MENU_FOLDER_VIEW = 1;
|
|
|
|
|
|
|
|
|
|
private static final int MENU_FOLDER_CHANGE_NAME = 2;
|
|
|
|
|
|
|
|
|
|
// 定义保存便签介绍的偏好设置参数名称
|
|
|
|
|
private static final String PREFERENCE_ADD_INTRODUCTION = "net.micode.notes.introduction";
|
|
|
|
|
|
|
|
|
|
// 枚举类型,表示列表编辑状态
|
|
|
|
|
private enum ListEditState {
|
|
|
|
|
NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 保存当前列表的编辑状态
|
|
|
|
|
private ListEditState mState;
|
|
|
|
|
|
|
|
|
|
// 后台查询操作的处理程序
|
|
|
|
|
private BackgroundQueryHandler mBackgroundQueryHandler;
|
|
|
|
|
|
|
|
|
|
// 便签列表数据适配器
|
|
|
|
|
private NotesListAdapter mNotesListAdapter;
|
|
|
|
|
|
|
|
|
|
// 显示便签列表的ListView
|
|
|
|
|
private ListView mNotesListView;
|
|
|
|
|
|
|
|
|
|
// 添加新便签的按钮
|
|
|
|
|
private Button mAddNewNote;
|
|
|
|
|
|
|
|
|
|
// 标识是否分发触摸事件
|
|
|
|
|
private boolean mDispatch;
|
|
|
|
|
|
|
|
|
|
// 原始触摸事件的Y坐标
|
|
|
|
|
private int mOriginY;
|
|
|
|
|
|
|
|
|
|
// 分发触摸事件的Y坐标
|
|
|
|
|
private int mDispatchY;
|
|
|
|
|
|
|
|
|
|
// 显示标题的文本视图
|
|
|
|
|
private TextView mTitleBar;
|
|
|
|
|
|
|
|
|
|
// 当前文件夹的ID
|
|
|
|
|
private long mCurrentFolderId;
|
|
|
|
|
|
|
|
|
|
// 内容解析器,用于访问应用程序的内容提供程序
|
|
|
|
|
private ContentResolver mContentResolver;
|
|
|
|
|
|
|
|
|
|
// 操作模式的回调接口
|
|
|
|
|
private ModeCallback mModeCallBack;
|
|
|
|
|
|
|
|
|
|
// 日志标签
|
|
|
|
|
private static final String TAG = "NotesListActivity";
|
|
|
|
|
|
|
|
|
|
// 便签列表滚动速率
|
|
|
|
|
public static final int NOTES_LISTVIEW_SCROLL_RATE = 30;
|
|
|
|
|
|
|
|
|
|
// 当前焦点便签数据项
|
|
|
|
|
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 "
|
|
|
|
|
+ NoteColumns.NOTES_COUNT + ">0)";
|
|
|
|
|
|
|
|
|
|
// 打开便签的请求码
|
|
|
|
|
private final static int REQUEST_CODE_OPEN_NODE = 102;
|
|
|
|
|
private final static int REQUEST_CODE_NEW_NODE = 103;
|
|
|
|
|
|
|
|
|
|
// 新建便签的请求码
|
|
|
|
|
private final static int REQUEST_CODE_NEW_NODE = 103;
|
|
|
|
|
}
|
|
|
|
|
@Override
|
|
|
|
|
/*
|
|
|
|
|
onCreate 方法是 Activity 的生命周期方法之一,当 Activity 创建时调用。在这个方法中,首先调用父类的 onCreate 方法进行初始化操作,然后设置布局文件为 note_list,最后调用 initResources 方法初始化资源,以及调用 setAppInfoFromRawRes 方法插入应用程序的介绍信息。
|
|
|
|
|
*/
|
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
setContentView(R.layout.note_list);
|
|
|
|
@ -146,7 +172,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
*/
|
|
|
|
|
setAppInfoFromRawRes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
onActivityResult 方法是在通过 startActivityForResult 启动的活动返回结果后调用。在这个方法中,首先判断返回结果是否成功,并且请求码是打开便签或新建便签的请求码,如果是,则通过调用 mNotesListAdapter.changeCursor(null) 方法来刷新便签列表。如果不满足条件,则调用父类的 onActivityResult 方法进行默认处理。
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
|
|
|
if (resultCode == RESULT_OK
|
|
|
|
@ -156,7 +184,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
setAppInfoFromRawRes 方法是用来从原始资源中读取应用程序的介绍信息并插入到便签列表中的。首先从默认的 SharedPreferences 中获取一个布尔值,该值记录了是否已经插入了介绍信息。如果没有插入介绍信息,则创建一个 StringBuilder 对象用于存储介绍信息,然后通过 getResources().openRawResource(R.raw.introduction) 打开原始资源文件 introduction,并将其读取到 StringBuilder 对象中。如果读取成功,则创建一个 WorkingNote 对象,指定根文件夹ID、App Widget ID、便签类型和颜色,并将介绍信息存储到便签中,最后保存便签并将插入介绍信息的布尔值设置为 true。如果读取或保存过程中发生错误,则打印错误日志并返回。
|
|
|
|
|
*/
|
|
|
|
|
private void setAppInfoFromRawRes() {
|
|
|
|
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
|
|
|
|
if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) {
|
|
|
|
@ -204,11 +234,23 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
/*
|
|
|
|
|
onStart 方法中调用 startAsyncNotesListQuery 开始异步查询笔记列表数据
|
|
|
|
|
*/
|
|
|
|
|
protected void onStart() {
|
|
|
|
|
super.onStart();
|
|
|
|
|
startAsyncNotesListQuery();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
initResources 方法中进行资源初始化,包括:
|
|
|
|
|
|
|
|
|
|
获取 ContentResolver 和 BackgroundQueryHandler 实例。
|
|
|
|
|
初始化 mCurrentFolderId。
|
|
|
|
|
初始化 mNotesListView,设置适配器,添加点击和长按监听器。
|
|
|
|
|
初始化 mAddNewNote 按钮,并设置点击和触摸监听器。
|
|
|
|
|
初始化一些变量和视图组件。
|
|
|
|
|
创建 ModeCallback 实例。
|
|
|
|
|
*/
|
|
|
|
|
private void initResources() {
|
|
|
|
|
mContentResolver = this.getContentResolver();
|
|
|
|
|
mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver());
|
|
|
|
@ -230,7 +272,12 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
mState = ListEditState.NOTE_LIST;
|
|
|
|
|
mModeCallBack = new ModeCallback();
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
ModeCallback 内部类实现了 ListView 的多选模式监听器和菜单项点击监听器,包括:
|
|
|
|
|
|
|
|
|
|
创建 ActionMode 时显示菜单和设置相关逻辑。
|
|
|
|
|
更新下拉菜单中的选中状态和显示文本。
|
|
|
|
|
*/
|
|
|
|
|
private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener {
|
|
|
|
|
private DropdownMenu mDropDownMenu;
|
|
|
|
|
private ActionMode mActionMode;
|
|
|
|
@ -268,7 +315,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
updateMenu 方法更新下拉菜单的标题和选项。
|
|
|
|
|
|
|
|
|
|
首先,获取选中的笔记数量。
|
|
|
|
|
然后,使用格式化字符串将选中的笔记数量与标题文本(资源字符串)合并。
|
|
|
|
|
更新下拉菜单的标题为合并后的文本。
|
|
|
|
|
根据选中状态更新下拉菜单中的全选/取消全选选项的文本和勾选状态。
|
|
|
|
|
*/
|
|
|
|
|
private void updateMenu() {
|
|
|
|
|
int selectedCount = mNotesListAdapter.getSelectedCount();
|
|
|
|
|
// Update dropdown menu
|
|
|
|
@ -285,17 +339,24 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
onPrepareActionMode 方法用于在 ActionMode 准备时执行一些操作,但在这个方法中并没有实现任何逻辑,返回值为 false。
|
|
|
|
|
*/
|
|
|
|
|
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
|
|
|
|
// TODO Auto-generated method stub
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//onActionItemClicked 方法用于在点击 ActionMode 的菜单项时执行一些操作,但在这个方法中并没有实现任何逻辑,返回值为 false。
|
|
|
|
|
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
|
|
|
|
// TODO Auto-generated method stub
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
onDestroyActionMode 方法在销毁 ActionMode 时执行一些操作,包括:
|
|
|
|
|
将适配器的选择模式设置为 false,取消选择模式。
|
|
|
|
|
将笔记列表视图设置为可长按。
|
|
|
|
|
将 mAddNewNote 按钮设置为可见。
|
|
|
|
|
*/
|
|
|
|
|
public void onDestroyActionMode(ActionMode mode) {
|
|
|
|
|
mNotesListAdapter.setChoiceMode(false);
|
|
|
|
|
mNotesListView.setLongClickable(true);
|
|
|
|
@ -305,13 +366,22 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
public void finishActionMode() {
|
|
|
|
|
mActionMode.finish();
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
onItemCheckedStateChanged 方法在列表项选中状态改变时执行一些操作,包括:
|
|
|
|
|
|
|
|
|
|
在适配器中设置指定位置的项是否被选中。
|
|
|
|
|
调用 updateMenu 方法更新下拉菜单。
|
|
|
|
|
*/
|
|
|
|
|
public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
|
|
|
|
|
boolean checked) {
|
|
|
|
|
mNotesListAdapter.setCheckedItem(position, checked);
|
|
|
|
|
updateMenu();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
onMenuItemClick 方法在点击菜单项时执行一些操作,包括:
|
|
|
|
|
检查是否有选中的项,如果没有选中的项则显示一个 Toast 提示用户选择内容。
|
|
|
|
|
返回 true 表示菜单项点击事件已被处理。
|
|
|
|
|
*/
|
|
|
|
|
public boolean onMenuItemClick(MenuItem item) {
|
|
|
|
|
if (mNotesListAdapter.getSelectedCount() == 0) {
|
|
|
|
|
Toast.makeText(NotesListActivity.this, getString(R.string.menu_select_none),
|
|
|
|
|