diff --git a/src/main/java/net/micode/notes/tool/DataUtils.java b/src/main/java/net/micode/notes/tool/DataUtils.java
index 82e8d10..42b64f7 100644
--- a/src/main/java/net/micode/notes/tool/DataUtils.java
+++ b/src/main/java/net/micode/notes/tool/DataUtils.java
@@ -131,21 +131,33 @@ public class DataUtils {
}
// 检查目标ID是否是一个文件夹(TYPE_FOLDER或TYPE_SYSTEM)
- Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, folderId),
- new String[] { NoteColumns.TYPE },
- null,
- null,
- null);
-
boolean isFolder = false;
- if (cursor != null) {
- if (cursor.moveToFirst()) {
- int type = cursor.getInt(0);
- if (type == Notes.TYPE_FOLDER || type == Notes.TYPE_SYSTEM) {
- isFolder = true;
+
+ // 特殊处理系统文件夹ID,它们是逻辑ID,不是实际的数据库记录ID
+ if (folderId == Notes.ID_ROOT_FOLDER ||
+ folderId == Notes.ID_TEMPARAY_FOLDER ||
+ folderId == Notes.ID_CALL_RECORD_FOLDER ||
+ folderId == Notes.ID_TRASH_FOLER ||
+ folderId == Notes.ID_PRIVACY_SPACE_FOLDER) {
+ isFolder = true;
+ Log.d(TAG, "Target is a system folder: " + folderId);
+ } else {
+ // 对于非系统文件夹,查询数据库验证
+ Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, folderId),
+ new String[] { NoteColumns.TYPE },
+ null,
+ null,
+ null);
+
+ if (cursor != null) {
+ if (cursor.moveToFirst()) {
+ int type = cursor.getInt(0);
+ if (type == Notes.TYPE_FOLDER || type == Notes.TYPE_SYSTEM) {
+ isFolder = true;
+ }
}
+ cursor.close();
}
- cursor.close();
}
if (!isFolder) {
@@ -456,4 +468,52 @@ public class DataUtils {
}
return snippet;
}
+
+ /**
+ * 获取指定文件夹中的便签数量
+ *
+ * 查询指定文件夹中包含的便签数量
+ *
+ *
+ * @param resolver ContentResolver对象
+ * @param folderId 文件夹ID
+ * @return 便签数量
+ */
+ public static int getNoteCount(ContentResolver resolver, long folderId) {
+ Cursor cursor = resolver.query(
+ Notes.CONTENT_NOTE_URI,
+ new String[] { "COUNT(*)" },
+ NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "=?",
+ new String[] { String.valueOf(Notes.TYPE_NOTE), String.valueOf(folderId) },
+ null
+ );
+
+ int count = 0;
+ if (cursor != null) {
+ if (cursor.moveToFirst()) {
+ try {
+ count = cursor.getInt(0);
+ } catch (IndexOutOfBoundsException e) {
+ Log.e(TAG, "get note count failed:" + e.toString());
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+ return count;
+ }
+
+ /**
+ * 获取未分类的便签数量
+ *
+ * 查询直接在根文件夹中的便签数量,即未分类的便签
+ *
+ *
+ * @param resolver ContentResolver对象
+ * @return 未分类的便签数量
+ */
+ public static int getUncategorizedNoteCount(ContentResolver resolver) {
+ // 未分类的便签就是直接在根文件夹中的便签
+ return getNoteCount(resolver, Notes.ID_ROOT_FOLDER);
+ }
}
diff --git a/src/main/java/net/micode/notes/ui/NotesListActivity.java b/src/main/java/net/micode/notes/ui/NotesListActivity.java
index 29f4275..6ffe5f4 100644
--- a/src/main/java/net/micode/notes/ui/NotesListActivity.java
+++ b/src/main/java/net/micode/notes/ui/NotesListActivity.java
@@ -70,6 +70,12 @@ import android.widget.Toast;
import android.widget.GridView;
import android.widget.BaseAdapter;
import android.view.ViewGroup;
+import android.widget.ScrollView;
+import androidx.drawerlayout.widget.DrawerLayout;
+import android.view.Gravity;
+import androidx.core.view.GravityCompat;
+import java.util.List;
+import java.util.ArrayList;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
@@ -115,10 +121,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
// 背景选项
private static final String[] BACKGROUND_OPTIONS = {
- "高山流水", "风中树叶", "长河落日"
+ "高山流水", "风中树叶", "长河落日"
};
private static final int[] BACKGROUND_RESOURCES = {
- R.drawable.background_mountain, R.drawable.background_leaves, R.drawable.background_sunset
+ R.drawable.background_mountain, R.drawable.background_leaves, R.drawable.background_sunset
};
private ListEditState mState;
@@ -152,9 +158,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private NoteItemData mFocusNoteDataItem;
- private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=? AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO;
+ private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=? AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER;
- private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.PARENT_ID + "=?) OR (" + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + NoteColumns.NOTES_COUNT + ">0)";
+ private static final String ROOT_FOLDER_SELECTION = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "=?";
// 隐私空间相关常量
private static final int REQUEST_CODE_PRIVACY_SPACE = 104;
@@ -179,11 +185,39 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private int mCurrentBackgroundResource = R.drawable.list_background;
private String mCurrentBackgroundPath = "";
+ // 侧边栏相关变量
+ private Button mSidebarToggleButton;
+ private ListView mFolderListView;
+ private SidebarAdapter mFolderAdapter;
+ private ListView mUserFolderListView;
+ private SidebarAdapter mUserFolderAdapter;
+ private ImageView mAddFolderButton;
+
+ // 标签选择相关
+ private String mSelectedTag = "";
+
+ // 分类侧边栏相关
+ private SidebarAdapter mCategoryAdapter = null;
+ private ListView mCategoryListView = null;
+
+ // 标签侧边栏相关
+ private SidebarAdapter mTagAdapter = null;
+ private ListView mTagListView = null;
+
+ // 快速视图相关
+ private SidebarAdapter mQuickViewAdapter = null;
+ private ListView mQuickViewListView = null;
+
+ // 统计相关
+ private TextView mTotalNotesTextView = null;
+ private TextView mPinnedNotesTextView = null;
+ private TextView mTodoNotesTextView = null;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.note_list);
-
+
// 获取隐私空间ID
Intent intent = getIntent();
if (intent != null) {
@@ -192,8 +226,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mCurrentPrivacySpaceId = "";
}
}
-
+
initResources();
+ initSidebar();
initBackground();
/**
@@ -370,13 +405,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mAddNewNote.setOnTouchListener(new NewNoteOnTouchListener());
mPrivacyBackButton = (Button) findViewById(R.id.btn_privacy_back);
mPrivacyBackButton.setOnClickListener(this);
+ mSidebarToggleButton = (Button) findViewById(R.id.btn_sidebar_toggle);
+ mSidebarToggleButton.setOnClickListener(this);
mDispatch = false;
mDispatchY = 0;
mOriginY = 0;
- mTitleBar = (TextView) findViewById(R.id.tv_title_bar);
mMainContent = (LinearLayout) findViewById(R.id.main_content);
// 获取根视图作为背景容器
- mBackgroundContainer = (RelativeLayout) findViewById(R.id.note_list_root);
+ mBackgroundContainer = (RelativeLayout) findViewById(R.id.main_content_container);
if (mBackgroundContainer == null) {
// 如果找不到,使用content view
View contentView = getWindow().getDecorView().findViewById(android.R.id.content);
@@ -404,7 +440,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
mState = ListEditState.NOTE_LIST;
mModeCallBack = new ModeCallback();
-
+
// 检查是否处于隐私空间中
updatePrivacySpaceUI();
@@ -747,8 +783,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
};
- // 当前选中的标签,用于筛选
- private String mSelectedTag = "";
+
private void startAsyncNotesListQuery() {
// 临时删除功能:输入"delete:1"删除ID为1的项目
@@ -766,45 +801,69 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
String baseSelection = "";
ArrayList argsList = new ArrayList<>();
- // 根据是否有搜索关键词构建不同的查询条件
- if (!TextUtils.isEmpty(mSearchQuery)) {
- // 有搜索关键词的情况
- if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
- // 根文件夹:需要将搜索条件应用到两个部分
- baseSelection = "((" + NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=? AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?))"
- + " OR (" + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + NoteColumns.NOTES_COUNT + ">0 AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)))";
- argsList.add(String.valueOf(mCurrentFolderId));
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSearchQuery + "%");
+ // 处理未分类情况
+ if (mCurrentFolderId == -1) {
+ // 未分类:查询所有不在文件夹中的便签
+ if (!TextUtils.isEmpty(mSearchQuery)) {
+ // 有搜索关键词的情况
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "=" + Notes.ID_ROOT_FOLDER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)";
argsList.add("%" + mSearchQuery + "%");
argsList.add("%" + mSearchQuery + "%");
argsList.add("%" + mSearchQuery + "%");
} else {
- // 普通文件夹
- baseSelection = NORMAL_SELECTION + " AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)";
- argsList.add(String.valueOf(mCurrentFolderId));
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSearchQuery + "%");
+ // 没有搜索关键词的情况
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "=" + Notes.ID_ROOT_FOLDER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER;
}
} else {
- // 没有搜索关键词的情况
- baseSelection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION : NORMAL_SELECTION;
- argsList.add(String.valueOf(mCurrentFolderId));
+ // 普通文件夹或根文件夹
+ // 根据是否有搜索关键词构建不同的查询条件
+ if (!TextUtils.isEmpty(mSearchQuery)) {
+ // 有搜索关键词的情况
+ if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
+ // 全部:查询所有文件夹中的便签,包括多级文件夹,但排除回收站
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)";
+ argsList.add("%" + mSearchQuery + "%");
+ argsList.add("%" + mSearchQuery + "%");
+ argsList.add("%" + mSearchQuery + "%");
+ } else {
+ // 普通文件夹:同时查询下一级文件夹和当前文件夹中的便签
+ baseSelection = "(" + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE + " OR " + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + ") AND " + NoteColumns.PARENT_ID + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)";
+ argsList.add(String.valueOf(mCurrentFolderId));
+ argsList.add("%" + mSearchQuery + "%");
+ argsList.add("%" + mSearchQuery + "%");
+ argsList.add("%" + mSearchQuery + "%");
+ }
+ } else {
+ // 没有搜索关键词的情况
+ if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
+ // 全部:查询所有文件夹中的便签,包括多级文件夹,但排除回收站
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER;
+ } else {
+ // 普通文件夹:同时查询下一级文件夹和当前文件夹中的便签
+ baseSelection = "(" + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE + " OR " + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + ") AND " + NoteColumns.PARENT_ID + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER;
+ argsList.add(String.valueOf(mCurrentFolderId));
+ }
+ }
}
// 添加标签筛选条件
if (!TextUtils.isEmpty(mSelectedTag)) {
- if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
+ if (mCurrentFolderId == -1) {
+ // 未分类情况
+ if (baseSelection.contains("AND")) {
+ baseSelection += " AND " + NoteColumns.TAGS + " LIKE ?";
+ } else {
+ baseSelection += " AND " + NoteColumns.TAGS + " LIKE ?";
+ }
+ argsList.add("%" + mSelectedTag + "%");
+ } else if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
// 根文件夹需要特殊处理
String tagCondition = " AND " + NoteColumns.TAGS + " LIKE ?";
// 根据是否有搜索关键词构建不同的标签筛选条件
if (!TextUtils.isEmpty(mSearchQuery)) {
// 有搜索关键词的情况
- baseSelection = "((" + NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=? AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)" + tagCondition + ")"
- + " OR (" + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + NoteColumns.NOTES_COUNT + ">0 AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)" + tagCondition + "))";
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)" + tagCondition;
// 重新构建参数列表
argsList.clear();
@@ -813,20 +872,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
argsList.add("%" + mSearchQuery + "%");
argsList.add("%" + mSearchQuery + "%");
argsList.add("%" + mSelectedTag + "%");
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSelectedTag + "%");
} else {
// 没有搜索关键词的情况
- baseSelection = "((" + NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?" + tagCondition + ")"
- + " OR (" + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + NoteColumns.NOTES_COUNT + ">0" + tagCondition + "))";
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + tagCondition;
// 重新构建参数列表
argsList.clear();
argsList.add(String.valueOf(mCurrentFolderId));
argsList.add("%" + mSelectedTag + "%");
- argsList.add("%" + mSelectedTag + "%");
}
} else {
// 普通文件夹
@@ -843,19 +896,27 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
if (!TextUtils.isEmpty(mCurrentPrivacySpaceId)) {
// 在隐私空间中,只显示该隐私空间的便签
String privacyCondition = NoteColumns.PRIVACY_SPACE_ID + "=?";
- if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
+ if (mCurrentFolderId == -1) {
+ // 未分类情况
+ baseSelection = "(" + baseSelection + ") AND " + privacyCondition;
+ argsList.add(mCurrentPrivacySpaceId);
+ } else if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
// 根文件夹需要特殊处理
if (!TextUtils.isEmpty(mSearchQuery) || !TextUtils.isEmpty(mSelectedTag)) {
// 有搜索关键词或标签的情况
baseSelection = "(" + baseSelection + ") AND " + privacyCondition;
} else {
// 没有搜索关键词和标签的情况
- baseSelection = "(" + NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=? AND " + privacyCondition + ")";
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "=? AND " + privacyCondition;
// 重新构建参数列表
argsList.clear();
argsList.add(String.valueOf(mCurrentFolderId));
argsList.add(mCurrentPrivacySpaceId);
}
+ if (!TextUtils.isEmpty(mSearchQuery) || !TextUtils.isEmpty(mSelectedTag)) {
+ // 有搜索关键词或标签的情况,需要添加隐私空间ID参数
+ argsList.add(mCurrentPrivacySpaceId);
+ }
} else {
// 普通文件夹
if (!TextUtils.isEmpty(mSearchQuery) || !TextUtils.isEmpty(mSelectedTag)) {
@@ -863,40 +924,39 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
baseSelection = "(" + baseSelection + ") AND " + privacyCondition;
} else {
// 没有搜索关键词和标签的情况
- baseSelection = NoteColumns.PARENT_ID + "=? AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + privacyCondition;
+ baseSelection = NoteColumns.PARENT_ID + "=? AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + privacyCondition;
// 重新构建参数列表
argsList.clear();
argsList.add(String.valueOf(mCurrentFolderId));
argsList.add(mCurrentPrivacySpaceId);
}
- }
- if (!TextUtils.isEmpty(mSearchQuery) || !TextUtils.isEmpty(mSelectedTag)) {
- // 有搜索关键词或标签的情况,需要添加隐私空间ID参数
- argsList.add(mCurrentPrivacySpaceId);
+ if (!TextUtils.isEmpty(mSearchQuery) || !TextUtils.isEmpty(mSelectedTag)) {
+ // 有搜索关键词或标签的情况,需要添加隐私空间ID参数
+ argsList.add(mCurrentPrivacySpaceId);
+ }
}
} else {
// 不在隐私空间中,只显示非隐私空间的便签
String privacyCondition = "(" + NoteColumns.PRIVACY_SPACE_ID + "='' OR " + NoteColumns.PRIVACY_SPACE_ID + " IS NULL)";
- if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
- // 根文件夹需要特殊处理
- baseSelection = "(" + baseSelection + ") AND " + privacyCondition;
- } else {
- // 普通文件夹
- if (baseSelection.contains("AND")) {
- baseSelection += " AND " + privacyCondition;
- } else {
- baseSelection += " WHERE " + privacyCondition;
- }
- }
+ baseSelection = "(" + baseSelection + ") AND " + privacyCondition;
}
selection = baseSelection;
selectionArgs = argsList.toArray(new String[argsList.size()]);
+ // 修改排序方式,确保文件夹显示在便签之前
+ String sortOrder = "";
+ if (mCurrentFolderId != Notes.ID_ROOT_FOLDER && mCurrentFolderId != -1) {
+ // 普通文件夹:先按类型排序(文件夹在前),再按修改日期排序
+ sortOrder = NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC";
+ } else {
+ // 根文件夹或未分类:按原排序方式
+ sortOrder = NoteColumns.IS_PINNED + " DESC," + NoteColumns.PIN_PRIORITY + " DESC," +
+ NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC";
+ }
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, selectionArgs,
- NoteColumns.IS_PINNED + " DESC," + NoteColumns.PIN_PRIORITY + " DESC," +
- NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
+ sortOrder);
}
private final class BackgroundQueryHandler extends AsyncQueryHandler {
@@ -953,12 +1013,24 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
private void batchDelete() {
+ if (mNotesListAdapter == null) {
+ Log.e(TAG, "mNotesListAdapter is null in batchDelete");
+ Toast.makeText(this, "删除失败:适配器为空", Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ final HashSet selectedIds = mNotesListAdapter.getSelectedItemIds();
+ if (selectedIds == null || selectedIds.isEmpty()) {
+ Log.e(TAG, "No items selected for deletion");
+ Toast.makeText(this, "删除失败:未选择便签", Toast.LENGTH_SHORT).show();
+ return;
+ }
+
new AsyncTask>() {
protected HashSet doInBackground(Void... unused) {
HashSet widgets = mNotesListAdapter.getSelectedWidget();
// Always move notes to trash folder for better user experience
- if (!DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter
- .getSelectedItemIds(), Notes.ID_TRASH_FOLER)) {
+ if (!DataUtils.batchMoveToFolder(mContentResolver, selectedIds, Notes.ID_TRASH_FOLER)) {
Log.e(TAG, "Move notes to trash folder error, should not happens");
}
return widgets;
@@ -974,7 +1046,15 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
}
- mModeCallBack.finishActionMode();
+ if (mModeCallBack != null) {
+ mModeCallBack.finishActionMode();
+ }
+ // 重新加载侧边栏数据,更新数量显示
+ loadSidebarData();
+ // 重新加载便签列表,让删除的便签立即消失
+ startAsyncNotesListQuery();
+ // 显示删除成功的提示
+ Toast.makeText(NotesListActivity.this, "已移至回收站", Toast.LENGTH_SHORT).show();
}
}.execute();
}
@@ -988,10 +1068,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
values.put(NoteColumns.PARENT_ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.LOCAL_MODIFIED, 1);
values.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
-
- int rows = mContentResolver.update(Notes.CONTENT_NOTE_URI, values,
+
+ int rows = mContentResolver.update(Notes.CONTENT_NOTE_URI, values,
NoteColumns.ID + "=?", new String[] { String.valueOf(itemId) });
-
+
if (rows > 0) {
Log.d(TAG, "Successfully moved item " + itemId + " to trash");
Toast.makeText(this, "项目已移至回收站", Toast.LENGTH_SHORT).show();
@@ -999,7 +1079,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
Log.e(TAG, "Failed to move item " + itemId + " to trash");
Toast.makeText(this, "删除失败,请重试", Toast.LENGTH_SHORT).show();
}
-
+
startAsyncNotesListQuery();
}
@@ -1067,9 +1147,12 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mCurrentPrivacySpaceId = "";
updatePrivacySpaceUI();
startAsyncNotesListQuery();
+ } else if (v.getId() == R.id.btn_sidebar_toggle) {
+ // 切换侧边栏显示/隐藏
+ toggleSidebar();
}
}
-
+
/**
* 更新隐私空间相关的UI元素
*/
@@ -1162,6 +1245,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
values.put(NoteColumns.PARENT_ID, mCurrentFolderId);
mContentResolver.insert(Notes.CONTENT_NOTE_URI, values);
+ // 重新加载侧边栏数据,确保新建的文件夹能显示出来
+ loadSidebarData();
}
dialog.dismiss();
}
@@ -1208,11 +1293,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
new String[] { String.valueOf(mCurrentFolderId) },
null
);
-
+
if (cursor != null && cursor.moveToFirst()) {
long parentId = cursor.getLong(0);
String folderName = cursor.getString(1);
-
+
if (parentId == Notes.ID_ROOT_FOLDER) {
// 返回到根文件夹
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
@@ -1255,7 +1340,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
}
-
+
startAsyncNotesListQuery();
break;
case CALL_RECORD_FOLDER:
@@ -1471,6 +1556,504 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
from.startActivityIfNeeded(intent, -1);
}
+ private View mAllItemView;
+ private TextView mAllTitleView;
+ private TextView mAllCountView;
+ private View mUncategorizedItemView;
+ private TextView mUncategorizedTitleView;
+ private TextView mUncategorizedCountView;
+
+ private void initSidebar() {
+ mAllItemView = findViewById(R.id.all_item);
+ mAllTitleView = findViewById(R.id.all_title);
+ mAllCountView = findViewById(R.id.all_count);
+ mUncategorizedItemView = findViewById(R.id.uncategorized_item);
+ mUncategorizedTitleView = findViewById(R.id.uncategorized_title);
+ mUncategorizedCountView = findViewById(R.id.uncategorized_count);
+ mUserFolderListView = findViewById(R.id.user_folder_list);
+ mAddFolderButton = findViewById(R.id.add_folder_button);
+
+ // 加载侧边栏数据
+ loadSidebarData();
+
+ // 设置全部项点击事件
+ mAllItemView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // 更新选中状态
+ updateTopItemSelection(true);
+ // 切换到全部
+ mCurrentFolderId = Notes.ID_ROOT_FOLDER;
+ startAsyncNotesListQuery();
+ // 关闭侧边栏
+ toggleSidebar();
+ }
+ });
+
+ // 设置未分类项点击事件
+ mUncategorizedItemView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // 更新选中状态
+ updateTopItemSelection(false);
+ // 切换到未分类
+ mCurrentFolderId = -1;
+ startAsyncNotesListQuery();
+ // 关闭侧边栏
+ toggleSidebar();
+ }
+ });
+
+ // 设置用户文件夹列表点击事件
+ mUserFolderListView.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(position);
+ if (item != null) {
+ // 更新选中状态
+ updateUserFolderSelection(position);
+ // 切换到对应的文件夹
+ mCurrentFolderId = item.getCategoryId();
+ startAsyncNotesListQuery();
+ // 关闭侧边栏
+ toggleSidebar();
+ }
+ }
+ });
+
+ // 设置用户文件夹列表长按事件,实现删除文件夹功能
+ mUserFolderListView.setOnItemLongClickListener(new OnItemLongClickListener() {
+ @Override
+ public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(position);
+ if (item != null) {
+ final long folderId = item.getCategoryId();
+ if (folderId == Notes.ID_ROOT_FOLDER) {
+ // 根文件夹不能删除
+ Toast.makeText(NotesListActivity.this, "根文件夹不能删除", Toast.LENGTH_SHORT).show();
+ return true;
+ }
+
+ // 显示确认删除对话框
+ AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
+ builder.setTitle("确认删除");
+ builder.setMessage("确定要删除文件夹 \"" + item.getTitle() + "\" 吗?");
+ builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // 删除文件夹
+ deleteFolder(folderId);
+ // 重新加载侧边栏数据
+ loadSidebarData();
+ // 显示删除成功提示
+ Toast.makeText(NotesListActivity.this, "文件夹已删除", Toast.LENGTH_SHORT).show();
+ }
+ });
+ builder.setNegativeButton("取消", null);
+ builder.show();
+ return true;
+ }
+ return false;
+ }
+ });
+
+ // 设置添加文件夹按钮点击事件
+ mAddFolderButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showCreateOrModifyFolderDialog(true);
+ // 关闭侧边栏
+ toggleSidebar();
+ }
+ });
+ }
+
+ private void loadSidebarData() {
+ // 加载全部项数据
+ int totalNotesCount = getTotalNoteCount();
+ mAllCountView.setText(String.valueOf(totalNotesCount));
+ if (totalNotesCount > 0) {
+ mAllCountView.setVisibility(View.VISIBLE);
+ } else {
+ mAllCountView.setVisibility(View.GONE);
+ }
+
+ // 加载未分类项数据
+ int uncategorizedCount = DataUtils.getUncategorizedNoteCount(mContentResolver);
+ mUncategorizedCountView.setText(String.valueOf(uncategorizedCount));
+ if (uncategorizedCount > 0) {
+ mUncategorizedCountView.setVisibility(View.VISIBLE);
+ } else {
+ mUncategorizedCountView.setVisibility(View.GONE);
+ }
+
+ // 加载用户文件夹(递归加载,显示层级结构)
+ List userFolderItems = new ArrayList<>();
+ loadFoldersRecursive(Notes.ID_ROOT_FOLDER, userFolderItems, 0);
+
+ // 创建并设置用户文件夹适配器
+ mUserFolderAdapter = new SidebarAdapter(this, userFolderItems);
+ mUserFolderListView.setAdapter(mUserFolderAdapter);
+
+ // 默认选中全部项
+ updateTopItemSelection(true);
+ }
+
+ private void updateFolderSelection(int position) {
+ // 取消所有顶部选项的选中状态
+ if (mFolderAdapter != null) {
+ for (int i = 0; i < mFolderAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mFolderAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+ // 设置当前选项为选中状态
+ SidebarAdapter.SidebarItem currentItem = (SidebarAdapter.SidebarItem) mFolderAdapter.getItem(position);
+ if (currentItem != null) {
+ currentItem.setSelected(true);
+ }
+ mFolderAdapter.notifyDataSetChanged();
+ }
+ // 取消所有用户文件夹的选中状态
+ if (mUserFolderAdapter != null) {
+ for (int i = 0; i < mUserFolderAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+ mUserFolderAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void updateTopItemSelection(boolean selectAll) {
+ // 重置所有顶部选项的状态
+ mAllItemView.setBackgroundColor(getResources().getColor(R.color.surface, null));
+ mAllTitleView.setTextColor(getResources().getColor(R.color.onSurface, null));
+ mAllCountView.setTextColor(getResources().getColor(R.color.primary, null));
+ mUncategorizedItemView.setBackgroundColor(getResources().getColor(R.color.surface, null));
+ mUncategorizedTitleView.setTextColor(getResources().getColor(R.color.onSurface, null));
+ mUncategorizedCountView.setTextColor(getResources().getColor(R.color.primary, null));
+
+ // 取消所有用户文件夹的选中状态
+ if (mUserFolderAdapter != null) {
+ for (int i = 0; i < mUserFolderAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+ mUserFolderAdapter.notifyDataSetChanged();
+ }
+
+ // 设置选中状态
+ if (selectAll) {
+ mAllItemView.setBackgroundColor(getResources().getColor(R.color.primary, null));
+ mAllTitleView.setTextColor(getResources().getColor(R.color.onPrimary, null));
+ mAllCountView.setTextColor(getResources().getColor(R.color.onPrimary, null));
+ } else {
+ mUncategorizedItemView.setBackgroundColor(getResources().getColor(R.color.primary, null));
+ mUncategorizedTitleView.setTextColor(getResources().getColor(R.color.onPrimary, null));
+ mUncategorizedCountView.setTextColor(getResources().getColor(R.color.onPrimary, null));
+ }
+ }
+
+ private void updateUserFolderSelection(int position) {
+ // 重置所有顶部选项的状态
+ mAllItemView.setBackgroundColor(getResources().getColor(R.color.surface, null));
+ mAllTitleView.setTextColor(getResources().getColor(R.color.onSurface, null));
+ mAllCountView.setTextColor(getResources().getColor(R.color.primary, null));
+ mUncategorizedItemView.setBackgroundColor(getResources().getColor(R.color.surface, null));
+ mUncategorizedTitleView.setTextColor(getResources().getColor(R.color.onSurface, null));
+ mUncategorizedCountView.setTextColor(getResources().getColor(R.color.primary, null));
+
+ // 取消所有用户文件夹的选中状态
+ if (mUserFolderAdapter != null) {
+ for (int i = 0; i < mUserFolderAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+
+ // 设置当前文件夹为选中状态
+ SidebarAdapter.SidebarItem currentItem = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(position);
+ if (currentItem != null) {
+ currentItem.setSelected(true);
+ }
+ mUserFolderAdapter.notifyDataSetChanged();
+ }
+ }
+
+ /**
+ * 更新侧边栏的选中状态,根据当前文件夹ID选择对应的侧边栏项
+ */
+ private void updateSidebarSelection() {
+ if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
+ // 当前在根文件夹,选中全部项
+ updateTopItemSelection(true);
+ } else if (mCurrentFolderId == -1) {
+ // 当前在未分类,选中未分类项
+ updateTopItemSelection(false);
+ } else {
+ // 当前在用户文件夹,找到并选中对应的文件夹项
+ if (mUserFolderAdapter != null) {
+ for (int i = 0; i < mUserFolderAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(i);
+ if (item != null && item.getCategoryId() == mCurrentFolderId) {
+ updateUserFolderSelection(i);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 获取所有文件夹中的便签总数,包括多级文件夹
+ */
+ private int getTotalNoteCount() {
+ // 递归获取所有文件夹中的便签数量
+ return getNoteCountRecursive(Notes.ID_ROOT_FOLDER);
+ }
+
+ /**
+ * 递归获取文件夹及其子文件夹中的便签数量
+ */
+ private int getNoteCountRecursive(long folderId) {
+ int count = 0;
+
+ // 获取当前文件夹中的便签数量(只统计普通便签,不统计待办事项)
+ Cursor noteCursor = mContentResolver.query(
+ Notes.CONTENT_NOTE_URI,
+ new String[] { "COUNT(*)" },
+ NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "=?",
+ new String[] { String.valueOf(Notes.TYPE_NOTE), String.valueOf(folderId) },
+ null
+ );
+
+ if (noteCursor != null) {
+ if (noteCursor.moveToFirst()) {
+ try {
+ count = noteCursor.getInt(0);
+ } catch (IndexOutOfBoundsException e) {
+ Log.e(TAG, "get note count failed:" + e.toString());
+ } finally {
+ noteCursor.close();
+ }
+ }
+ }
+
+ // 获取当前文件夹中的子文件夹
+ Cursor folderCursor = mContentResolver.query(
+ Notes.CONTENT_NOTE_URI,
+ new String[] { NoteColumns.ID },
+ NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "=?",
+ new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(folderId) },
+ null
+ );
+
+ if (folderCursor != null) {
+ while (folderCursor.moveToNext()) {
+ try {
+ long childFolderId = folderCursor.getLong(0);
+ // 递归获取子文件夹中的便签数量
+ count += getNoteCountRecursive(childFolderId);
+ } catch (IndexOutOfBoundsException e) {
+ Log.e(TAG, "get folder id failed:" + e.toString());
+ }
+ }
+ folderCursor.close();
+ }
+
+ return count;
+ }
+
+ /**
+ * 递归加载文件夹及其子文件夹,显示层级结构
+ */
+ private void loadFoldersRecursive(long parentFolderId, List folderItems, int level) {
+ // 获取当前文件夹下的子文件夹
+ Cursor folderCursor = mContentResolver.query(
+ Notes.CONTENT_NOTE_URI,
+ new String[]{NoteColumns.ID, NoteColumns.SNIPPET, NoteColumns.NOTES_COUNT},
+ NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "=?",
+ new String[]{String.valueOf(Notes.TYPE_FOLDER), String.valueOf(parentFolderId)},
+ NoteColumns.MODIFIED_DATE + " DESC"
+ );
+
+ if (folderCursor != null) {
+ while (folderCursor.moveToNext()) {
+ try {
+ long folderId = folderCursor.getLong(0);
+ String folderName = folderCursor.getString(1);
+ int noteCount = folderCursor.getInt(2);
+
+ // 根据层级添加缩进
+ StringBuilder indentedName = new StringBuilder();
+ for (int i = 0; i < level; i++) {
+ indentedName.append(" "); // 每级添加两个空格的缩进
+ }
+ indentedName.append(folderName);
+
+ // 添加文件夹项
+ folderItems.add(new SidebarAdapter.SidebarItem(indentedName.toString(), noteCount, folderId));
+
+ // 递归加载子文件夹
+ loadFoldersRecursive(folderId, folderItems, level + 1);
+ } catch (IndexOutOfBoundsException e) {
+ Log.e(TAG, "load folder failed:" + e.toString());
+ }
+ }
+ folderCursor.close();
+ }
+ }
+
+ private void initCategoryData() {
+ // 模拟分类数据,实际应该从数据库获取
+ List categories = new ArrayList<>();
+ categories.add(new SidebarAdapter.SidebarItem("全部便签", 15, Notes.ID_ROOT_FOLDER));
+ categories.add(new SidebarAdapter.SidebarItem("工作", 8, 1));
+ categories.add(new SidebarAdapter.SidebarItem("生活", 5, 2));
+ categories.add(new SidebarAdapter.SidebarItem("学习", 2, 3));
+
+ mCategoryAdapter = new SidebarAdapter(this, categories);
+ mCategoryListView.setAdapter(mCategoryAdapter);
+
+ // 默认选中第一个分类
+ if (!categories.isEmpty()) {
+ categories.get(0).setSelected(true);
+ mCategoryAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void initTagData() {
+ // 模拟标签数据,实际应该从数据库获取
+ List tags = new ArrayList<>();
+ tags.add(new SidebarAdapter.SidebarItem("重要", 5, "重要"));
+ tags.add(new SidebarAdapter.SidebarItem("紧急", 3, "紧急"));
+ tags.add(new SidebarAdapter.SidebarItem("想法", 4, "想法"));
+ tags.add(new SidebarAdapter.SidebarItem("计划", 2, "计划"));
+
+ mTagAdapter = new SidebarAdapter(this, tags);
+ mTagListView.setAdapter(mTagAdapter);
+ }
+
+ private void initQuickViewData() {
+ // 初始化快捷视图数据
+ List quickViews = new ArrayList<>();
+ quickViews.add(new SidebarAdapter.SidebarItem("全部便签", 15, SidebarAdapter.SidebarItem.QuickViewType.ALL));
+ quickViews.add(new SidebarAdapter.SidebarItem("已置顶", 3, SidebarAdapter.SidebarItem.QuickViewType.PINNED));
+ quickViews.add(new SidebarAdapter.SidebarItem("今天", 2, SidebarAdapter.SidebarItem.QuickViewType.TODAY));
+ quickViews.add(new SidebarAdapter.SidebarItem("无标签", 6, SidebarAdapter.SidebarItem.QuickViewType.UNTAGGED));
+
+ mQuickViewAdapter = new SidebarAdapter(this, quickViews);
+ mQuickViewListView.setAdapter(mQuickViewAdapter);
+
+ // 默认选中第一个快捷视图
+ if (!quickViews.isEmpty()) {
+ quickViews.get(0).setSelected(true);
+ mQuickViewAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void initNoteStatistics() {
+ // 模拟统计数据,实际应该从数据库获取
+ mTotalNotesTextView.setText("15");
+ mPinnedNotesTextView.setText("3");
+ mTodoNotesTextView.setText("2");
+ }
+
+ private void updateCategorySelection(int position) {
+ // 取消所有分类的选中状态
+ if (mCategoryAdapter != null) {
+ for (int i = 0; i < mCategoryAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mCategoryAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+ // 设置当前分类为选中状态
+ SidebarAdapter.SidebarItem currentItem = (SidebarAdapter.SidebarItem) mCategoryAdapter.getItem(position);
+ if (currentItem != null) {
+ currentItem.setSelected(true);
+ }
+ mCategoryAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void updateTagSelection(int position) {
+ // 取消所有标签的选中状态
+ if (mTagAdapter != null) {
+ for (int i = 0; i < mTagAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mTagAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+ // 设置当前标签为选中状态
+ SidebarAdapter.SidebarItem currentItem = (SidebarAdapter.SidebarItem) mTagAdapter.getItem(position);
+ if (currentItem != null) {
+ currentItem.setSelected(true);
+ }
+ mTagAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void updateQuickViewSelection(int position) {
+ // 取消所有快捷视图的选中状态
+ if (mQuickViewAdapter != null) {
+ for (int i = 0; i < mQuickViewAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mQuickViewAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+ // 设置当前快捷视图为选中状态
+ SidebarAdapter.SidebarItem currentItem = (SidebarAdapter.SidebarItem) mQuickViewAdapter.getItem(position);
+ if (currentItem != null) {
+ currentItem.setSelected(true);
+ }
+ mQuickViewAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void applyQuickViewFilter(SidebarAdapter.SidebarItem.QuickViewType type) {
+ // 根据快捷视图类型应用不同的筛选条件
+ switch (type) {
+ case ALL:
+ // 清除所有筛选条件
+ mCurrentFolderId = Notes.ID_ROOT_FOLDER;
+ mSelectedTag = "";
+ break;
+ case PINNED:
+ // 只显示已置顶的便签
+ // 这里需要在startAsyncNotesListQuery中添加置顶筛选逻辑
+ break;
+ case TODAY:
+ // 只显示今天创建或修改的便签
+ // 这里需要在startAsyncNotesListQuery中添加日期筛选逻辑
+ break;
+ case UNTAGGED:
+ // 只显示无标签的便签
+ mSelectedTag = "";
+ // 这里需要在startAsyncNotesListQuery中添加无标签筛选逻辑
+ break;
+ }
+ }
+
+ private void toggleSidebar() {
+ DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);
+ if (drawerLayout != null) {
+ if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
+ drawerLayout.closeDrawer(GravityCompat.START);
+ } else {
+ drawerLayout.openDrawer(GravityCompat.START);
+ }
+ }
+ }
+
private class OnListItemClickListener implements OnItemClickListener {
public void onItemClick(AdapterView> parent, View view, int position, long id) {
@@ -1485,27 +2068,18 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return;
}
- switch (mState) {
- case NOTE_LIST:
- case SUB_FOLDER:
- 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 or SUB_FOLDER");
- }
- break;
- case CALL_RECORD_FOLDER:
- if (item.getType() == Notes.TYPE_NOTE) {
- openNode(item);
- } else {
- Log.e(TAG, "Wrong note type in CALL_RECORD_FOLDER");
- }
- break;
- default:
- break;
+ // 处理便签点击
+ if (item.getType() == Notes.TYPE_NOTE) {
+ openNode(item);
+ }
+ // 处理文件夹点击
+ else if (item.getType() == Notes.TYPE_FOLDER) {
+ // 更新当前文件夹ID
+ mCurrentFolderId = item.getId();
+ // 重新加载便签列表,显示该文件夹的内容
+ startAsyncNotesListQuery();
+ // 更新侧边栏的选中状态
+ updateSidebarSelection();
}
}
}
@@ -1736,14 +2310,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
mCurrentBackgroundType = sp.getString(PREFERENCE_BACKGROUND + "_type", BACKGROUND_TYPE_DEFAULT);
mCurrentBackgroundPath = sp.getString(PREFERENCE_BACKGROUND + "_path", "");
-
+
if (BACKGROUND_TYPE_DEFAULT.equals(mCurrentBackgroundType)) {
int backgroundIndex = sp.getInt(PREFERENCE_BACKGROUND + "_index", 0);
if (backgroundIndex >= 0 && backgroundIndex < BACKGROUND_RESOURCES.length) {
mCurrentBackgroundResource = BACKGROUND_RESOURCES[backgroundIndex];
}
}
-
+
// 更新背景
updateBackground();
}
@@ -1755,7 +2329,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
if (mBackgroundContainer == null) {
return;
}
-
+
try {
if (BACKGROUND_TYPE_DEFAULT.equals(mCurrentBackgroundType)) {
// 使用默认背景
@@ -1773,23 +2347,23 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
// 如果是内部存储路径
bitmap = android.graphics.BitmapFactory.decodeFile(mCurrentBackgroundPath);
}
-
+
if (bitmap != null) {
// 计算屏幕尺寸
android.util.DisplayMetrics displayMetrics = new android.util.DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
-
+
// 缩放图片以适配屏幕
android.graphics.Bitmap scaledBitmap = android.graphics.Bitmap.createScaledBitmap(
bitmap, screenWidth, screenHeight, true);
-
+
android.graphics.drawable.BitmapDrawable drawable = new android.graphics.drawable.BitmapDrawable(getResources(), scaledBitmap);
// 设置背景图片的缩放方式
drawable.setTileModeXY(android.graphics.Shader.TileMode.CLAMP, android.graphics.Shader.TileMode.CLAMP);
mBackgroundContainer.setBackground(drawable);
-
+
// 释放原始 bitmap
if (bitmap != scaledBitmap) {
bitmap.recycle();
@@ -1817,7 +2391,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
SharedPreferences.Editor editor = sp.edit();
editor.putString(PREFERENCE_BACKGROUND + "_type", mCurrentBackgroundType);
editor.putString(PREFERENCE_BACKGROUND + "_path", mCurrentBackgroundPath);
-
+
if (BACKGROUND_TYPE_DEFAULT.equals(mCurrentBackgroundType)) {
// 找到当前背景资源的索引
int index = 0;
@@ -1829,7 +2403,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
editor.putInt(PREFERENCE_BACKGROUND + "_index", index);
}
-
+
editor.apply();
}
@@ -1839,12 +2413,12 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private void showBackgroundSelectorDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("选择背景");
-
+
// 创建背景选项数组,添加从相册选择的选项
String[] options = new String[BACKGROUND_OPTIONS.length + 1];
System.arraycopy(BACKGROUND_OPTIONS, 0, options, 0, BACKGROUND_OPTIONS.length);
options[BACKGROUND_OPTIONS.length] = "从相册选择";
-
+
builder.setItems(options, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
@@ -1865,7 +2439,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
});
-
+
builder.show();
}
diff --git a/src/main/java/net/micode/notes/ui/SidebarAdapter.java b/src/main/java/net/micode/notes/ui/SidebarAdapter.java
new file mode 100644
index 0000000..060a3e1
--- /dev/null
+++ b/src/main/java/net/micode/notes/ui/SidebarAdapter.java
@@ -0,0 +1,142 @@
+package net.micode.notes.ui;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import net.micode.notes.R;
+
+import java.util.List;
+
+public class SidebarAdapter extends BaseAdapter {
+ private Context mContext;
+ private List mItems;
+
+ public SidebarAdapter(Context context, List items) {
+ mContext = context;
+ mItems = items;
+ }
+
+ @Override
+ public int getCount() {
+ return mItems != null ? mItems.size() : 0;
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mItems != null ? mItems.get(position) : null;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = LayoutInflater.from(mContext).inflate(R.layout.sidebar_item, parent, false);
+ }
+
+ SidebarItem item = mItems.get(position);
+ TextView titleTextView = convertView.findViewById(R.id.item_title);
+ TextView countTextView = convertView.findViewById(R.id.item_count);
+
+ titleTextView.setText(item.getTitle());
+ if (item.getCount() > 0) {
+ countTextView.setVisibility(View.VISIBLE);
+ countTextView.setText(String.valueOf(item.getCount()));
+ } else {
+ countTextView.setVisibility(View.GONE);
+ }
+
+ if (item.isSelected()) {
+ convertView.setBackgroundColor(mContext.getResources().getColor(R.color.primary, null));
+ titleTextView.setTextColor(mContext.getResources().getColor(R.color.onPrimary, null));
+ countTextView.setTextColor(mContext.getResources().getColor(R.color.onPrimary, null));
+ } else {
+ convertView.setBackgroundColor(mContext.getResources().getColor(R.color.surface, null));
+ titleTextView.setTextColor(mContext.getResources().getColor(R.color.onSurface, null));
+ countTextView.setTextColor(mContext.getResources().getColor(R.color.primary, null));
+ }
+
+ return convertView;
+ }
+
+ public static class SidebarItem {
+ private String mTitle;
+ private int mCount;
+ private boolean mSelected;
+ private String mTag;
+ private long mCategoryId;
+ private QuickViewType mQuickViewType;
+
+ public SidebarItem(String title) {
+ mTitle = title;
+ mCount = 0;
+ mSelected = false;
+ }
+
+ public SidebarItem(String title, int count) {
+ mTitle = title;
+ mCount = count;
+ mSelected = false;
+ }
+
+ public SidebarItem(String title, int count, long categoryId) {
+ mTitle = title;
+ mCount = count;
+ mSelected = false;
+ mCategoryId = categoryId;
+ }
+
+ public SidebarItem(String title, int count, String tag) {
+ mTitle = title;
+ mCount = count;
+ mSelected = false;
+ mTag = tag;
+ }
+
+ public SidebarItem(String title, int count, QuickViewType type) {
+ mTitle = title;
+ mCount = count;
+ mSelected = false;
+ mQuickViewType = type;
+ }
+
+ public String getTitle() {
+ return mTitle;
+ }
+
+ public int getCount() {
+ return mCount;
+ }
+
+ public boolean isSelected() {
+ return mSelected;
+ }
+
+ public void setSelected(boolean selected) {
+ mSelected = selected;
+ }
+
+ public String getTag() {
+ return mTag;
+ }
+
+ public long getCategoryId() {
+ return mCategoryId;
+ }
+
+ public QuickViewType getQuickViewType() {
+ return mQuickViewType;
+ }
+
+ public enum QuickViewType {
+ ALL, PINNED, TODAY, UNTAGGED
+ }
+ }
+}
diff --git a/src/main/res/drawable/count_badge.xml b/src/main/res/drawable/count_badge.xml
new file mode 100644
index 0000000..6e5f178
--- /dev/null
+++ b/src/main/res/drawable/count_badge.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/drawable/ic_folder_add.xml b/src/main/res/drawable/ic_folder_add.xml
new file mode 100644
index 0000000..13f65ef
--- /dev/null
+++ b/src/main/res/drawable/ic_folder_add.xml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/src/main/res/drawable/ic_format_color_bold.jpg b/src/main/res/drawable/ic_format_color_bold.jpg
new file mode 100644
index 0000000..29c3985
Binary files /dev/null and b/src/main/res/drawable/ic_format_color_bold.jpg differ
diff --git a/src/main/res/drawable/ic_format_color_bold.png b/src/main/res/drawable/ic_format_color_bold.png
deleted file mode 100644
index b877ab8..0000000
Binary files a/src/main/res/drawable/ic_format_color_bold.png and /dev/null differ
diff --git a/src/main/res/drawable/ic_format_color_fill.jpg b/src/main/res/drawable/ic_format_color_fill.jpg
new file mode 100644
index 0000000..4913d74
Binary files /dev/null and b/src/main/res/drawable/ic_format_color_fill.jpg differ
diff --git a/src/main/res/drawable/ic_format_color_fill.png b/src/main/res/drawable/ic_format_color_fill.png
deleted file mode 100644
index ab75d8b..0000000
Binary files a/src/main/res/drawable/ic_format_color_fill.png and /dev/null differ
diff --git a/src/main/res/drawable/ic_format_color_text.jpg b/src/main/res/drawable/ic_format_color_text.jpg
new file mode 100644
index 0000000..1e1221c
Binary files /dev/null and b/src/main/res/drawable/ic_format_color_text.jpg differ
diff --git a/src/main/res/drawable/ic_format_color_text.png b/src/main/res/drawable/ic_format_color_text.png
deleted file mode 100644
index 645e83f..0000000
Binary files a/src/main/res/drawable/ic_format_color_text.png and /dev/null differ
diff --git a/src/main/res/drawable/ic_format_italic.jpg b/src/main/res/drawable/ic_format_italic.jpg
new file mode 100644
index 0000000..12c85d7
Binary files /dev/null and b/src/main/res/drawable/ic_format_italic.jpg differ
diff --git a/src/main/res/drawable/ic_format_italic.png b/src/main/res/drawable/ic_format_italic.png
deleted file mode 100644
index bdb9a04..0000000
Binary files a/src/main/res/drawable/ic_format_italic.png and /dev/null differ
diff --git a/src/main/res/drawable/ic_format_underlined.jpg b/src/main/res/drawable/ic_format_underlined.jpg
new file mode 100644
index 0000000..6c6d44a
Binary files /dev/null and b/src/main/res/drawable/ic_format_underlined.jpg differ
diff --git a/src/main/res/drawable/ic_format_underlined.png b/src/main/res/drawable/ic_format_underlined.png
deleted file mode 100644
index 31ea58c..0000000
Binary files a/src/main/res/drawable/ic_format_underlined.png and /dev/null differ
diff --git a/src/main/res/layout/note_list.xml b/src/main/res/layout/note_list.xml
index 636abff..1ad1008 100644
--- a/src/main/res/layout/note_list.xml
+++ b/src/main/res/layout/note_list.xml
@@ -15,175 +15,221 @@
limitations under the License.
-->
-
-
+
+ android:layout_height="match_parent">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
+
+ android:fontFamily="sans-serif-medium" />
-
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/src/main/res/layout/sidebar_item.xml b/src/main/res/layout/sidebar_item.xml
new file mode 100644
index 0000000..f6b2d8d
--- /dev/null
+++ b/src/main/res/layout/sidebar_item.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/layout/sidebar_layout.xml b/src/main/res/layout/sidebar_layout.xml
new file mode 100644
index 0000000..80d181b
--- /dev/null
+++ b/src/main/res/layout/sidebar_layout.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/values/colors.xml b/src/main/res/values/colors.xml
index 550310d..d967f9c 100644
--- a/src/main/res/values/colors.xml
+++ b/src/main/res/values/colors.xml
@@ -50,4 +50,6 @@
#FF9800
#E0E0E0
#BDBDBD
+ #E7E0EC
+ #49454F
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index e084a43..23739b7 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -242,6 +242,7 @@
Translation failed. Please check your network connection and try again.
Failed to load image
Extracted Content
+ 正在提取内容...
Insert
Cancel
Content inserted successfully