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

828 lines
35 KiB

This file contains ambiguous Unicode characters!

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

/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.ui;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
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;
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 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;
private ListView mNotesListView;
private Button mAddNewNote;
private boolean mDispatch;
private int mOriginY;
private int mDispatchY;
private TextView mTitleBar;
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;
@Override
protected void onCreate(Bundle savedInstanceState) {
// 初始化父类的创建方法
super.onCreate(savedInstanceState);
// 设置当前活动的布局文件为 note_list
setContentView(R.layout.note_list);
// 初始化应用资源
initResources();
/**
* 当用户首次使用应用程序时插入介绍信息
*/
setAppInfoFromRawRes();
}
/**
* 处理活动结果回调
*
* 当其他活动返回结果时,本方法被调用以处理返回的数据
* 本方法特别关注的是当用户从其他活动返回时,是否创建或打开了一个笔记
* 如果是,那么将刷新笔记列表的光标,以反映数据的变更
*
* @param requestCode 请求码,标识启动其他活动时的请求类型
* @param resultCode 结果码,标识返回结果的状态
* @param data 返回的数据可能为null
*/
@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对象用于存储应用介绍信息是否已添加的状态
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
// 检查是否已经添加了介绍信息,如果没有,则执行添加操作
if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) {
// 初始化StringBuilder对象用于存储读取的介绍信息文本
StringBuilder sb = new StringBuilder();
InputStream in = null;
try {
// 打开raw资源文件介绍信息
in = getResources().openRawResource(R.raw.introduction);
if (in != null) {
// 创建InputStreamReader对象用于将输入流转换为字符流
InputStreamReader isr = new InputStreamReader(in);
// 创建BufferedReader对象用于逐行读取字符流
BufferedReader br = new BufferedReader(isr);
char [] buf = new char[1024];
int len = 0;
// 循环读取文件内容,直到文件结束
while ((len = br.read(buf)) > 0) {
// 将读取的内容追加到StringBuilder中
sb.append(buf, 0, len);
}
} else {
// 如果文件读取失败,则记录错误日志并返回
Log.e(TAG, "Read introduction file error");
return;
}
} catch (IOException e) {
// 捕获IOException异常并记录堆栈信息
e.printStackTrace();
return;
} finally {
// 在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());
// 尝试保存笔记对象如果成功则在SharedPreferences中标记已添加介绍信息
if (note.saveNote()) {
sp.edit().putBoolean(PREFERENCE_ADD_INTRODUCTION, true).commit();
} else {
// 如果保存介绍信息失败,则记录错误日志
Log.e(TAG, "Save introduction note error");
return;
}
}
}
/**
* Activity启动时调用的方法
* 该方法重写了父类的onStart方法用于在Activity变为可见时执行特定操作
*/
@Override
protected void onStart() {
super.onStart(); // 调用父类的onStart方法确保必要的初始化工作完成
startAsyncNotesListQuery(); // 启动异步查询笔记列表的操作,可能包括从数据库或网络获取数据
}
/**
* 初始化应用资源
* 该方法主要用于初始化应用所需的资源包括内容解析器、后台查询处理器、当前文件夹ID、
* 笔记列表视图、适配器、按钮及其事件监听器等
*/
private void initResources() {
// 初始化内容解析器
mContentResolver = this.getContentResolver();
// 创建后台查询处理器实例
mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver());
// 设置当前文件夹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 class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener {
private DropdownMenu mDropDownMenu;
private ActionMode mActionMode;
private MenuItem mMoveMenu;
/**
* 初始化操作模式和菜单
*
* @param mode 操作模式接口,用于操作模式的管理
* @param menu 菜单接口,用于显示操作模式下的菜单项
* @return 始终返回 true表示操作模式已成功创建
*
* 此方法用于在操作模式启动时初始化相关的菜单和UI组件它负责充气菜单、设置菜单项的可见性和事件监听器
* 以及更新笔记列表的选中模式和长按行为此外,它还设置了自定义视图以显示在操作模式中,并初始化了下拉菜单
*/
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);
// 加载自定义视图用于操作模式
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;
}
});
// 操作模式初始化成功返回true
return true;
}
/**
* 更新菜单项,根据笔记适配器中的选择状态
* 此方法用于动态更新下拉菜单标题以及“全选/取消全选”选项的状态,根据用户选择的笔记数量
*/
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);
}
}
}
/**
* 当ActionMode被准备时调用用于在用户界面显示上下文操作模式之前进行最终准备
* 此方法允许对菜单项进行最后的修改,例如启用、禁用或修改菜单项的可见性
*
* @param mode 当前的ActionMode实例提供了对上下文操作模式的访问
* @param menu 菜单实例,包含所有菜单项,允许在显示前进行修改
*
* @return 返回false表示菜单未被更新不需要重新显示如果返回true则表示菜单已更新需要重新显示
*/
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
/**
* 处理ActionMode中的菜单项点击事件
*
* @param mode 当前的ActionMode实例
* @param item 被点击的菜单项
* @return 返回处理结果如果返回true则表示该点击事件已经完全处理如果返回false则表示该点击事件未被处理
*/
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// TODO Auto-generated method stub
return false;
}
/**
* 当ActionMode结束时调用的方法
* 该方法主要用于重置应用界面到非ActionMode状态
*
* @param mode ActionMode实例表示被销毁的动作模式
*/
public void onDestroyActionMode(ActionMode mode) {
// 禁用列表的多选模式
mNotesListAdapter.setChoiceMode(false);
// 恢复列表项的长按事件
mNotesListView.setLongClickable(true);
// 重新显示添加新笔记的按钮
mAddNewNote.setVisibility(View.VISIBLE);
}
/**
* 结束Action Mode
*
* 此方法用于结束当前的Action Mode状态Action Mode通常在用户进行特定操作时启动
* 例如批量选择或编辑模式完成这些操作后,调用此方法可以正常结束该模式
*/
public void finishActionMode() {
mActionMode.finish();
}
/**
* 当列表项的复选状态发生变化时调用该方法
*
* @param mode ActionMode实例用于处理操作模式
* @param position 列表项的位置,表示哪个列表项的复选状态发生了变化
* @param id 列表项的ID用于唯一标识列表项
* @param checked 列表项的新复选状态true表示已选中false表示未选中
*/
public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
boolean checked) {
// 更新适配器中对应位置列表项的复选状态
mNotesListAdapter.setCheckedItem(position, checked);
// 更新菜单状态,以反映当前选中的列表项数量
updateMenu();
}
/**
* 处理菜单项点击事件
*
* @param item 被点击的菜单项
* @return 如果事件被处理则返回true否则返回false
*/
public boolean onMenuItemClick(MenuItem item) {
// 检查当前选中的笔记数量如果为0则提示用户并阻止进一步操作
if (mNotesListAdapter.getSelectedCount() == 0) {
Toast.makeText(NotesListActivity.this, getString(R.string.menu_select_none),
Toast.LENGTH_SHORT).show();
return true;
}
// 根据被点击的菜单项ID执行相应的操作
switch (item.getItemId()) {
case R.id.delete:
// 创建确认对话框,确认用户是否想要删除选中的笔记
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;
}
}
private class NewNoteOnTouchListener implements OnTouchListener {
/**
* 处理视图上的触摸事件。
*
* @param v 被触摸的视图。
* @param event 发生的运动事件,包含动作和坐标。
* @return 如果触摸事件被此方法处理则返回 true否则返回 false。
*/
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();
// 减去标题栏的高度
if (mState == ListEditState.SUB_FOLDER) {
eventY -= mTitleBar.getHeight();
start -= mTitleBar.getHeight();
}
// 当点击“新建笔记”按钮的透明部分时,将事件分发给按钮后面的列表视图。
// “新建笔记”按钮的透明部分可以用公式 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))) {
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: {
};
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");
}
// 返回备份文本导出的结果
return backup.exportToText();
}
// 在后台任务完成后执行的操作
@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();
}
}
}.execute();
}
// 判断是否处于同步模式
private boolean isSyncMode() {
return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
}
// 启动偏好设置活动
private void startPreferenceActivity() {
Activity from = getParent() != null ? getParent() : this;
Intent intent = new Intent(from, NotesPreferenceActivity.class);
from.startActivityIfNeeded(intent, -1);
}
// 列表项点击监听器
private class OnListItemClickListener implements OnItemClickListener {
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;
}
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;
}
}
}
}
// 启动查询目标文件夹的任务
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);
}
}
return false;
// 返回备份文本导出的结果
return backup.exportToText();
}
// 在后台任务完成后执行的操作
@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();
}
}
}.execute();
}
// 判断是否处于同步模式
private boolean isSyncMode() {
return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
}
// 启动偏好设置活动
private void startPreferenceActivity() {
Activity from = getParent() != null ? getParent() : this;
Intent intent = new Intent(from, NotesPreferenceActivity.class);
from.startActivityIfNeeded(intent, -1);
}
// 列表项点击监听器
private class OnListItemClickListener implements OnItemClickListener {
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;
}
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;
}
}
}
}
// 启动查询目标文件夹的任务
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);
}
}
return false;
}
}