diff --git a/src/main/java/net/micode/notes/MainActivity.java b/src/main/java/net/micode/notes/MainActivity.java index 105fc40..8091753 100644 --- a/src/main/java/net/micode/notes/MainActivity.java +++ b/src/main/java/net/micode/notes/MainActivity.java @@ -1,13 +1,5 @@ - package net.micode.notes; -/** - * 笔记应用的主活动类,作为应用的入口点。 - *

- * 该类是小米笔记应用的主活动,负责初始化应用界面和处理窗口边距设置。 - *

- */ - import android.os.Bundle; import androidx.activity.EdgeToEdge; @@ -18,15 +10,6 @@ import androidx.core.view.WindowInsetsCompat; public class MainActivity extends AppCompatActivity { - /** - * 活动创建时调用的方法,初始化应用界面和窗口设置。 - *

- * 该方法启用了边缘到边缘显示模式,设置了活动布局,并处理了系统栏 - * 的边距问题,确保内容不会被系统UI遮挡。 - *

- * - * @param savedInstanceState 保存的实例状态,用于恢复活动状态 - */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/src/main/java/net/micode/notes/data/Notes.java b/src/main/java/net/micode/notes/data/Notes.java index 5d83908..4b82197 100644 --- a/src/main/java/net/micode/notes/data/Notes.java +++ b/src/main/java/net/micode/notes/data/Notes.java @@ -211,22 +211,29 @@ public class Notes { public static final String LOCAL_MODIFIED = "local_modified"; /** - * 移动到临时文件夹之前的原始父ID - *

类型: INTEGER

+ * 原始父ID + *

类型: INTEGER (long)

*/ public static final String ORIGIN_PARENT_ID = "origin_parent_id"; /** - * GTask ID + * GTASK ID *

类型: TEXT

*/ public static final String GTASK_ID = "gtask_id"; /** * 版本号 - *

类型: INTEGER (long)

+ *

类型: INTEGER

*/ public static final String VERSION = "version"; + + /** + * 置顶状态 + *

类型: INTEGER

+ *

0表示未置顶,1表示置顶

+ */ + public static final String PINNED = "pinned"; } public interface DataColumns { diff --git a/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java b/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java index f6b9c37..5eccfec 100644 --- a/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java +++ b/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java @@ -35,7 +35,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { // 数据库文件名 private static final String DB_NAME = "note.db"; // 数据库版本号,用于升级控制 - private static final int DB_VERSION = 4; + private static final int DB_VERSION = 5; /** * 数据库表名常量定义 @@ -56,7 +56,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { * 笔记表创建SQL语句 * 包含笔记/文件夹的基本属性:ID、父文件夹ID、提醒时间、背景色、创建/修改时间等 */ - private static final String CREATE_NOTE_TABLE_SQL = + private static final String CREATE_NOTE_TABLE_SQL = "CREATE TABLE " + TABLE.NOTE + "(" + NoteColumns.ID + " INTEGER PRIMARY KEY," + NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + @@ -74,7 +74,8 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + - NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + + NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0," + + NoteColumns.PINNED + " INTEGER NOT NULL DEFAULT 0" + ")"; /** @@ -378,6 +379,12 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { oldVersion++; } + // 版本4升级到版本5 + if (oldVersion == 4) { + upgradeToV5(db); + oldVersion++; + } + // 如果需要,重新创建触发器 if (reCreateTriggers) { reCreateNoteTableTriggers(db); @@ -429,4 +436,13 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0"); } + + /** + * 升级到版本5:添加置顶字段,用于便签置顶功能 + * @param db 数据库实例 + */ + private void upgradeToV5(SQLiteDatabase db) { + db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.PINNED + + " INTEGER NOT NULL DEFAULT 0"); + } } \ No newline at end of file diff --git a/src/main/java/net/micode/notes/model/Note.java b/src/main/java/net/micode/notes/model/Note.java index 4c7931d..44935dd 100644 --- a/src/main/java/net/micode/notes/model/Note.java +++ b/src/main/java/net/micode/notes/model/Note.java @@ -260,7 +260,7 @@ public class Note { /** * 日志标签 */ - private static final String TAG = NoteData.class.getSimpleName(); + private static final String TAG = "NoteData"; /** * 构造方法,初始化笔记数据 diff --git a/src/main/java/net/micode/notes/ui/NoteItemData.java b/src/main/java/net/micode/notes/ui/NoteItemData.java index 2ffa01d..44825ee 100644 --- a/src/main/java/net/micode/notes/ui/NoteItemData.java +++ b/src/main/java/net/micode/notes/ui/NoteItemData.java @@ -53,6 +53,7 @@ public class NoteItemData { NoteColumns.TYPE, NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE, + NoteColumns.PINNED, }; /** @@ -114,12 +115,22 @@ public class NoteItemData { * 查询结果中小组件类型列的索引 */ private static final int WIDGET_TYPE_COLUMN = 11; + + /** + * 查询结果中置顶状态列的索引 + */ + private static final int PINNED_COLUMN = 12; /** * 笔记ID */ private long mId; + /** + * 置顶状态 + */ + private boolean mPinned; + /** * 提醒日期 */ @@ -230,6 +241,7 @@ public class NoteItemData { mType = cursor.getInt(TYPE_COLUMN); mWidgetId = cursor.getInt(WIDGET_ID_COLUMN); mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN); + mPinned = (cursor.getInt(PINNED_COLUMN) > 0) ? true : false; mPhoneNumber = ""; if (mParentId == Notes.ID_CALL_RECORD_FOLDER) { @@ -447,6 +459,22 @@ public class NoteItemData { public boolean isCallRecord() { return (mParentId == Notes.ID_CALL_RECORD_FOLDER && !TextUtils.isEmpty(mPhoneNumber)); } + + /** + * 获取置顶状态 + * @return 置顶状态,true表示已置顶,false表示未置顶 + */ + public boolean isPinned() { + return mPinned; + } + + /** + * 设置置顶状态 + * @param pinned 置顶状态,true表示置顶,false表示取消置顶 + */ + public void setPinned(boolean pinned) { + mPinned = pinned; + } /** * 获取笔记类型(静态方法) diff --git a/src/main/java/net/micode/notes/ui/NotesListActivity.java b/src/main/java/net/micode/notes/ui/NotesListActivity.java index b72aba0..f1d9277 100644 --- a/src/main/java/net/micode/notes/ui/NotesListActivity.java +++ b/src/main/java/net/micode/notes/ui/NotesListActivity.java @@ -132,14 +132,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt /** 新建笔记按钮 */ private Button mAddNewNote; - /** 是否分发触摸事件 */ - private boolean mDispatch; - - /** 原始Y坐标 */ - private int mOriginY; - - /** 分发Y坐标 */ - private int mDispatchY; + // 删除不再使用的触摸事件相关变量 + // private boolean mDispatch; + // private int mOriginY; + // private int mDispatchY; /** 标题栏文本视图 */ private TextView mTitleBar; @@ -152,6 +148,15 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt /** 模式回调 */ private ModeCallback mModeCallBack; + + /** 是否分发触摸事件 */ + private boolean mDispatch; + + /** 原始Y坐标 */ + private int mOriginY; + + /** 分发Y坐标 */ + private int mDispatchY; /** 日志标签 */ private static final String TAG = "NotesListActivity"; @@ -167,7 +172,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt /** 根文件夹选择条件 */ private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns.TYPE + "<>" - + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)") + " OR (" + + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" + " OR (" + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + NoteColumns.NOTES_COUNT + ">0)"; @@ -196,6 +201,19 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt * Insert an introduction when user firstly use this application */ setAppInfoFromRawRes(); + + // 注册Android 13+的返回键回调 + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { + getOnBackInvokedDispatcher().registerOnBackInvokedCallback( + android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT, + new android.window.OnBackInvokedCallback() { + @Override + public void onBackInvoked() { + handleBackPress(); + } + } + ); + } } /** @@ -356,6 +374,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt mMoveMenu.setVisible(true); mMoveMenu.setOnMenuItemClickListener(this); } + // 添加置顶菜单初始化 + MenuItem pinMenu = menu.findItem(R.id.pin); + if (pinMenu != null) { + pinMenu.setOnMenuItemClickListener(this); + } mActionMode = mode; mNotesListAdapter.setChoiceMode(true); mNotesListView.setLongClickable(false); @@ -515,6 +538,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt case R.id.move: startQueryDestinationFolders(); break; + case R.id.pin: + togglePinnedStatus(); + break; default: return false; } @@ -622,7 +648,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt 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"); + }, NoteColumns.PINNED + " DESC," + NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC"); } /** @@ -755,6 +781,54 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt }.execute(); } + /** + * 切换选中便签的置顶状态 + */ + private void togglePinnedStatus() { + final HashSet selectedIds = mNotesListAdapter.getSelectedItemIds(); + final int selectedCount = mNotesListAdapter.getSelectedCount(); + + new AsyncTask() { + protected Void doInBackground(Void... unused) { + for (Long noteId : selectedIds) { + // 查询当前便签的置顶状态 + Cursor cursor = mContentResolver.query(Notes.CONTENT_NOTE_URI, + new String[]{NoteColumns.PINNED}, + NoteColumns.ID + "=?", + new String[]{String.valueOf(noteId)}, + null); + + if (cursor != null && cursor.moveToFirst()) { + int currentPinned = cursor.getInt(0); + // 切换置顶状态 + int newPinned = currentPinned == 1 ? 0 : 1; + + ContentValues values = new ContentValues(); + values.put(NoteColumns.PINNED, newPinned); + + mContentResolver.update(Notes.CONTENT_NOTE_URI, + values, + NoteColumns.ID + "=?", + new String[]{String.valueOf(noteId)}); + + cursor.close(); + } + } + return null; + } + + @Override + protected void onPostExecute(Void unused) { + Toast.makeText(NotesListActivity.this, + "已更新 " + selectedCount + " 个便签", + Toast.LENGTH_SHORT).show(); + // 重新查询数据,更新列表 + startAsyncNotesListQuery(); + mModeCallBack.finishActionMode(); + } + }.execute(); + } + /** * 删除文件夹 *

@@ -991,8 +1065,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt * 3. 如果在根文件夹中,调用默认的返回处理 *

*/ - @Override - public void onBackPressed() { + private void handleBackPress() { switch (mState) { case SUB_FOLDER: mCurrentFolderId = Notes.ID_ROOT_FOLDER; @@ -1015,6 +1088,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt } } + @Override + public void onBackPressed() { + handleBackPress(); + } + /** * 更新部件 *

diff --git a/src/main/res/layout/note_edit.xml b/src/main/res/layout/note_edit.xml index 10b2aa7..e0cf16b 100644 --- a/src/main/res/layout/note_edit.xml +++ b/src/main/res/layout/note_edit.xml @@ -19,6 +19,7 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/list_background" + android:fitsSystemWindows="true" xmlns:android="http://schemas.android.com/apk/res/android"> + android:fadingEdgeLength="0dip" + android:paddingTop="16dp"> + android:background="@drawable/list_background" + android:fitsSystemWindows="true"> + android:layout_gravity="bottom" + android:layout_marginBottom="16dp" /> diff --git a/src/main/res/menu/note_list_options.xml b/src/main/res/menu/note_list_options.xml index daac008..749aa3e 100644 --- a/src/main/res/menu/note_list_options.xml +++ b/src/main/res/menu/note_list_options.xml @@ -28,4 +28,9 @@ android:title="@string/menu_delete" android:icon="@drawable/menu_delete" android:showAsAction="always|withText" /> + + \ No newline at end of file diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 09f75ed..6039b43 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -44,6 +44,8 @@ 搜索 删除 移动到文件夹 + 置顶 + 取消置顶 选中了 %d 项 没有选中项,操作无效 全选 diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 55df868..02d3841 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -48,6 +48,8 @@ Search Delete Move to folder + Pin + Unpin %d selected Nothing selected, the operation is invalid Select all