diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 28431d4..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,116 +0,0 @@
-/src/Notes/app/build
-###Android###
-# Built application files
-*.apk
-*.ap_
-
-# Files for the ART/Dalvik VM
-*.dex
-
-# Java class files
-*.class
-
-# Generated files
-/src/Notes/app/bin/
-/src/Notes/app/gen/
-/src/Notes/app/out/
-
-# Gradle files
-/src/Notes/app/.gradle/
-/src/Notes/app/build/
-
-# Local configuration file (sdk path, etc)
-/src/Notes/app/local.properties
-
-# Proguard folder generated by Eclipse
-/src/Notes/app/proguard/
-
-# Log Files
-*.log
-
-# Crashlytics plugin (for Android Studio and IntelliJ)
-/src/Notes/app/com_crashlytics_export_strings.xml
-/src/Notes/app/crashlytics.properties
-/src/Notes/app/crashlytics-build.properties
-/src/Notes/app/fabric.properties
-
-# Android Studio Navigation editor temp files
-/src/Notes/app/.navigation/
-
-# Android Studio captures folder
-captures/
-
-# Keystore files
-*.jks
-
-# External native build folder generated in Android Studio 2.2 and later
-.externalNativeBuild
-
-###macOS###
-*.DS_Store
-.AppleDouble
-.LSOverride
-
-# Icon must end with two \r
-Icon
-
-
-# Thumbnails
-._*
-
-# Files that might appear in the root of a volume
-.DocumentRevisions-V100
-.fseventsd
-.Spotlight-V100
-.TemporaryItems
-.Trashes
-.VolumeIcon.icns
-.com.apple.timemachine.donotpresent
-
-# Directories potentially created on remote AFP share
-.AppleDB
-.AppleDesktop
-Network Trash Folder
-Temporary Items
-.apdisk
-
-###Linux###
-*~
-
-# temporary files which can be created if a process still has a handle open of a deleted file
-.fuse_hidden*
-
-# KDE directory preferences
-.directory
-
-# Linux trash folder which might appear on any partition or disk
-.Trash-*
-
-# .nfs files are created when an open file is removed but is still being accessed
-.nfs*
-
-###Windows###
-# Windows image file caches
-Thumbs.db
-ehthumbs.db
-
-# Folder config file
-Desktop.ini
-
-# Recycle Bin used on file shares
-$RECYCLE.BIN/
-
-# Windows Installer files
-*.cab
-*.msi
-*.msm
-*.msp
-
-# Windows shortcuts
-*.lnk
-###IntelliJ###
-*.iml
-*.ipr
-*.iws
-/src/Notes/app/.idea/
-/src/Notes/app/libs/
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 26d3352..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 69b28af..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 35eb1dd..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index 4757b3d..2989e2d 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
-# Notes
+# 小米便签
diff --git a/doc/小米便签开源代码的泛读报告.docx b/doc/小米便签开源代码的泛读报告.docx
index 2a5d451..c33be62 100644
Binary files a/doc/小米便签开源代码的泛读报告.docx and b/doc/小米便签开源代码的泛读报告.docx differ
diff --git a/readme.md b/readme.md
deleted file mode 100644
index 4757b3d..0000000
--- a/readme.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Notes
-
diff --git a/src/Notes/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/src/Notes/.gradle/buildOutputCleanup/buildOutputCleanup.lock
index 954fdfe..927f3d8 100644
Binary files a/src/Notes/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/src/Notes/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ
diff --git a/src/Notes/.gradle/buildOutputCleanup/cache.properties b/src/Notes/.gradle/buildOutputCleanup/cache.properties
index 299c01e..0eba958 100644
--- a/src/Notes/.gradle/buildOutputCleanup/cache.properties
+++ b/src/Notes/.gradle/buildOutputCleanup/cache.properties
@@ -1,2 +1,2 @@
-#Sun Apr 02 08:57:27 CST 2023
-gradle.version=7.5
+#Sun Apr 23 18:04:59 CST 2023
+gradle.version=8.0
diff --git a/src/Notes/.gradle/buildOutputCleanup/outputFiles.bin b/src/Notes/.gradle/buildOutputCleanup/outputFiles.bin
index 1d2c594..5e353d5 100644
Binary files a/src/Notes/.gradle/buildOutputCleanup/outputFiles.bin and b/src/Notes/.gradle/buildOutputCleanup/outputFiles.bin differ
diff --git a/src/Notes/.gradle/file-system.probe b/src/Notes/.gradle/file-system.probe
index efea422..9cc85ce 100644
Binary files a/src/Notes/.gradle/file-system.probe and b/src/Notes/.gradle/file-system.probe differ
diff --git a/src/Notes/app/build.gradle b/src/Notes/app/build.gradle
index ae0b4c4..1e45ad2 100644
--- a/src/Notes/app/build.gradle
+++ b/src/Notes/app/build.gradle
@@ -17,4 +17,5 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
+ namespace 'net.micode.notes'
}
diff --git a/src/Notes/app/src/main/AndroidManifest.xml b/src/Notes/app/src/main/AndroidManifest.xml
index 41511bc..96920fb 100644
--- a/src/Notes/app/src/main/AndroidManifest.xml
+++ b/src/Notes/app/src/main/AndroidManifest.xml
@@ -17,11 +17,11 @@
+ android:versionName="0.1">
-
@@ -37,19 +37,19 @@
+ android:label="@string/app_name">
-
-
+
+
+ android:windowSoftInputMode="adjustPan">
@@ -60,14 +60,16 @@
+ android:theme="@style/NoteTheme">
-
+
@@ -75,6 +77,7 @@
+
@@ -93,14 +96,14 @@
+ android:exported="false"
+ android:multiprocess="true" />
+ android:exported="true"
+ android:label="@string/app_widget2x2">
@@ -112,11 +115,27 @@
android:resource="@xml/widget_2x_info" />
+
+
+
+
+
+
+
+
+
+
+
+ android:exported="true"
+ android:label="@string/app_widget4x4">
@@ -130,7 +149,8 @@
-
@@ -139,26 +159,22 @@
-
+ android:process=":remote">
-
+ android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
-
+ android:theme="@android:style/Theme.Holo.Light">
-
+ android:exported="false">
= HOURS_IN_HALF_DAY;
inflate(context, R.layout.datetime_picker, this);
+// 首先调用了父类 ViewGroup 的构造函数 super(context) 来初始化 DateTimePicker 实例。然后,代码使用 Calendar.getInstance() 获取一个 Calendar 对象,该对象表示当前日期和时间。变量 mIsAm 被初始化为当前小时数是否大于等于 12,以确定当前用户选择的是 AM 还是 PM。
mDateSpinner = (NumberPicker) findViewById(R.id.date);
mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL);
mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL);
mDateSpinner.setOnValueChangedListener(mOnDateChangedListener);
+// 获取了布局文件中 ID 为 date 的 NumberPicker 控件,并将其赋值给 mDateSpinner 变量。然后,使用 setMinValue() 和 setMaxValue() 方法将 mDateSpinner 的最小值和最大值分别设置为 DATE_SPINNER_MIN_VAL 和 DATE_SPINNER_MAX_VAL。使用 setOnValueChangedListener() 方法将 mDateSpinner 的值更改监听器设置为 mOnDateChangedListener。这意味着当 mDateSpinner 的值更改时,将会调用 mOnDateChangedListener 中的方法来处理这个事件。
mHourSpinner = (NumberPicker) findViewById(R.id.hour);
mHourSpinner.setOnValueChangedListener(mOnHourChangedListener);
@@ -190,13 +205,18 @@ public class DateTimePicker extends FrameLayout {
mMinuteSpinner.setMaxValue(MINUT_SPINNER_MAX_VAL);
mMinuteSpinner.setOnLongPressUpdateInterval(100);
mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener);
+// 获取了布局文件中 ID 为 hour 和 minute 的 NumberPicker 控件,并将它们分别赋值给 mHourSpinner 和 mMinuteSpinner 变量。然后,使用 setOnValueChangedListener() 方法将 mHourSpinner 和 mMinuteSpinner 控件的值更改监听器分别设置为 mOnHourChangedListener 和 mOnMinuteChangedListener。
+// 接下来,使用 setMinValue() 和 setMaxValue() 方法将 mMinuteSpinner 的最小值和最大值分别设置为 MINUT_SPINNER_MIN_VAL 和 MINUT_SPINNER_MAX_VAL,以限制分钟选择器的范围。
+// 最后,使用 setOnLongPressUpdateInterval() 方法将 mMinuteSpinner 的长按更新间隔设置为 100 毫秒。这意味着当用户长按 mMinuteSpinner 中的增加或减少按钮时,它将以每 100 毫秒的速度连续增加或减少 mMinuteSpinner 的值。
+// 通过设置 NumberPicker 的值更改监听器和其他属性,代码实现了一个可以选择小时和分钟的控件,并将它们分别绑定到 mHourSpinner 和 mMinuteSpinner 变量上,以便在之后的操作中使用。
- String[] stringsForAmPm = new DateFormatSymbols().getAmPmStrings();
+ String[] stringsForAmPm = new DateFormatSymbols().getAmPmStrings();//获取了当前设备的日期格式符号,并使用 getAmPmStrings() 方法从中获取 AM/PM 格式符号的字符串数组,并将其赋值给 stringsForAmPm 变量。
mAmPmSpinner = (NumberPicker) findViewById(R.id.amPm);
mAmPmSpinner.setMinValue(AMPM_SPINNER_MIN_VAL);
mAmPmSpinner.setMaxValue(AMPM_SPINNER_MAX_VAL);
- mAmPmSpinner.setDisplayedValues(stringsForAmPm);
- mAmPmSpinner.setOnValueChangedListener(mOnAmPmChangedListener);
+// 获取了布局文件中 ID 为 amPm 的 NumberPicker 控件,并将其赋值给 mAmPmSpinner 变量。使用 setMinValue() 和 setMaxValue() 方法将 mAmPmSpinner 的最小值和最大值分别设置为 AMPM_SPINNER_MIN_VAL 和 AMPM_SPINNER_MAX_VAL,以限制 AM/PM 选择器的范围。
+ mAmPmSpinner.setDisplayedValues(stringsForAmPm);//使用 setDisplayedValues() 方法将 stringsForAmPm 数组设置为 mAmPmSpinner 的显示值。这意味着 AM/PM 选择器将显示 stringsForAmPm 数组中的字符串,而不是默认的数字值。
+ mAmPmSpinner.setOnValueChangedListener(mOnAmPmChangedListener);//使用 setOnValueChangedListener() 方法将 mAmPmSpinner 的值更改监听器设置为 mOnAmPmChangedListener。这意味着当用户更改 AM/PM 选择器的值时,将调用 mOnAmPmChangedListener 中的方法来处理这个事件。
// update controls to initial state
updateDateControl();
@@ -204,6 +224,7 @@ public class DateTimePicker extends FrameLayout {
updateAmPmControl();
set24HourView(is24HourView);
+// 代码调用了 updateDateControl()、updateHourControl() 和 updateAmPmControl() 方法,以便将控件显示为当前日期和时间的值。然后,代码调用了 set24HourView() 方法将选择器的时间格式设置为 24 小时制或 12 小时制。
// set to current time
setCurrentDate(date);
@@ -212,6 +233,7 @@ public class DateTimePicker extends FrameLayout {
// set the content descriptions
mInitialising = false;
+// 调用了 setCurrentDate() 方法将选择器的日期和时间设置为指定的日期和时间,调用 setEnabled() 方法将选择器的可用状态设置为指定的值,并将 mInitialising 标志设置为 false,以便通知选择器已完成初始化。
}
@Override
@@ -219,13 +241,17 @@ public class DateTimePicker extends FrameLayout {
if (mIsEnabled == enabled) {
return;
}
+// 当调用 setEnabled() 方法时,如果传入的参数 enabled 与当前的 mIsEnabled 变量的值相同,说明选择器的可用状态没有发生变化,直接返回即可。
super.setEnabled(enabled);
mDateSpinner.setEnabled(enabled);
mMinuteSpinner.setEnabled(enabled);
mHourSpinner.setEnabled(enabled);
mAmPmSpinner.setEnabled(enabled);
mIsEnabled = enabled;
+// 代码首先调用父类的 setEnabled() 方法,将整个时间选择器的可用状态设置为传入的参数 enabled。然后,分别调用 mDateSpinner、mMinuteSpinner、mHourSpinner 和 mAmPmSpinner 的 setEnabled() 方法,将它们的可用状态也设置为传入的参数 enabled。
+//最后,将 mIsEnabled 变量的值设置为传入的参数 enabled,以便在下一次调用 setEnabled() 方法时使用。
}
+// 重写 setEnabled() 方法,代码实现了一个可以同时设置整个时间选择器的可用状态的功能。
@Override
public boolean isEnabled() {
@@ -428,11 +454,14 @@ public class DateTimePicker extends FrameLayout {
}
mIs24HourView = is24HourView;
mAmPmSpinner.setVisibility(is24HourView ? View.GONE : View.VISIBLE);
+// 当传入的参数 is24HourView 与当前的 mIs24HourView 变量的值相同时,方法直接返回。否则,将 mIs24HourView 变量的值设置为传入的参数 is24HourView,表示时间选择器的显示格式已经更改。
int hour = getCurrentHourOfDay();
updateHourControl();
setCurrentHour(hour);
updateAmPmControl();
+// 获取当前的小时数并调用 updateHourControl() 方法更新小时选择器,以保持小时选择器的一致性。接着,使用 setCurrentHour() 方法将当前的小时数设置回时间选择器,并调用 updateAmPmControl() 方法更新 AM/PM 选择器。
}
+//通过设置 AM/PM 选择器的可见性和更新时间选择器的小时控件和 AM/PM 控件,代码实现了一个可以切换时间选择器显示格式的功能。
private void updateDateControl() {
Calendar cal = Calendar.getInstance();
@@ -447,6 +476,8 @@ public class DateTimePicker extends FrameLayout {
mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2);
mDateSpinner.invalidate();
}
+// 用于更新日期选择器的显示值。它首先获取当前日期并将其设置为日历实例 cal 的时间。然后,cal 被设置为一周的第一天,以确保日期选择器显示一周的日期。
+//接下来,使用 setDisplayedValues() 方法将日期选择器的显示值设置为 null,以便重新生成新的日期显示值。然后,使用循环从 cal 中获取每一天的日期,并将其格式化为 MM.dd EEEE 的格式,并将其存储在一个字符串数组中。最后,使用 setDisplayedValues() 方法将新的日期显示值设置为 mDateSpinner,并将当前选择的日期值设置为一周的中间值,以保持日期选择器的一致性。
private void updateAmPmControl() {
if (mIs24HourView) {
@@ -457,6 +488,7 @@ public class DateTimePicker extends FrameLayout {
mAmPmSpinner.setVisibility(View.VISIBLE);
}
}
+// 用于更新 AM/PM 选择器的显示值。如果时间选择器为 24 小时格式,则将 AM/PM 选择器隐藏;否则,根据当前是否为 AM,将 AM/PM 选择器的值设置为 Calendar.AM 或 Calendar.PM,并将其可见性设置为 View.VISIBLE。
private void updateHourControl() {
if (mIs24HourView) {
@@ -467,6 +499,7 @@ public class DateTimePicker extends FrameLayout {
mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW);
}
}
+// 用于更新小时选择器的显示值。如果时间选择器为 24 小时格式,则将小时选择器的最小值和最大值分别设置为 HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW 和 HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW;否则,将小时选择器的最小值和最大值分别设置为 HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW 和 HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW。
/**
* Set the callback that indicates the 'Set' button has been pressed.
diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java b/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java
index 2c47ba4..a7c67ce 100644
--- a/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java
+++ b/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java
@@ -39,6 +39,7 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener
public interface OnDateTimeSetListener {
void OnDateTimeSet(AlertDialog dialog, long date);
}
+// 实现了一个 OnDateTimeSetListener 接口,该接口定义了一个 OnDateTimeSet() 方法,用于在用户选择日期时间后通知调用者。
public DateTimePickerDialog(Context context, long date) {
super(context);
@@ -55,6 +56,7 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener
updateTitle(mDate.getTimeInMillis());
}
});
+// 包含了一个 DateTimePicker 控件,用于让用户选择日期和时间。通过 mDateTimePicker.setOnDateTimeChangedListener() 方法,当用户选择日期和时间时,将更新 mDate 的值,并使用 updateTitle() 方法更新对话框的标题。
mDate.setTimeInMillis(date);
mDate.set(Calendar.SECOND, 0);
mDateTimePicker.setCurrentDate(mDate.getTimeInMillis());
@@ -67,6 +69,7 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener
public void set24HourView(boolean is24HourView) {
mIs24HourView = is24HourView;
}
+//set24HourView() 方法,用于设置日期时间选择器是否为 24 小时格式。默认情况下,该值将由系统的设置决定。
public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) {
mOnDateTimeSetListener = callBack;
@@ -86,5 +89,6 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener
mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis());
}
}
+// 重写了 onClick() 方法,以便在用户点击“确定”按钮后,将用户选择的日期时间作为参数传递到 OnDateTimeSet() 方法中,从而通知调用者。
}
\ No newline at end of file
diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/DropdownMenu.java b/src/Notes/app/src/main/java/net/micode/notes/ui/DropdownMenu.java
index 613dc74..44cca84 100644
--- a/src/Notes/app/src/main/java/net/micode/notes/ui/DropdownMenu.java
+++ b/src/Notes/app/src/main/java/net/micode/notes/ui/DropdownMenu.java
@@ -31,6 +31,7 @@ public class DropdownMenu {
private Button mButton;
private PopupMenu mPopupMenu;
private Menu mMenu;
+// 一个 Button 控件,用于显示菜单的标题,以及一个 PopupMenu 对象,用于显示菜单项。在构造函数中,该类接受一个菜单资源 ID,并使用 mPopupMenu.getMenuInflater().inflate() 方法从 XML 资源中加载菜单项,然后将菜单项添加到 mMenu 对象中。
public DropdownMenu(Context context, Button button, int menuId) {
mButton = button;
@@ -43,19 +44,22 @@ public class DropdownMenu {
mPopupMenu.show();
}
});
+// 重写了 setOnClickListener() 方法,以便在用户点击 Button 控件时显示下拉菜单。
}
+// 在 Button 控件上注册一个单击事件监听器,并在该监听器中实现下拉菜单的显示逻辑。
public void setOnDropdownMenuItemClickListener(OnMenuItemClickListener listener) {
if (mPopupMenu != null) {
mPopupMenu.setOnMenuItemClickListener(listener);
}
}
+// setOnDropdownMenuItemClickListener() 方法,用于设置菜单项的点击监听器。通过这个方法,应用程序可以在用户选择菜单项时执行相应的操作。
public MenuItem findItem(int id) {
return mMenu.findItem(id);
- }
+ }//findItem() 方法用于查找指定 ID 的菜单项
public void setTitle(CharSequence title) {
mButton.setText(title);
- }
+ }//用于设置菜单的标题。
}
diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java b/src/Notes/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java
index 96b77da..71a4f49 100644
--- a/src/Notes/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java
+++ b/src/Notes/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java
@@ -47,6 +47,7 @@ public class FoldersListAdapter extends CursorAdapter {
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return new FolderListItem(context);
}
+// 用于创建新的视图,该方法返回一个新的 FolderListItem 对象,它是一个自定义的 LinearLayout,用于显示文件夹列表项的布局。
@Override
public void bindView(View view, Context context, Cursor cursor) {
@@ -56,12 +57,14 @@ public class FoldersListAdapter extends CursorAdapter {
((FolderListItem) view).bind(folderName);
}
}
+// 用于绑定视图和数据,该方法会将数据从 Cursor 对象中读取出来,并将其绑定到 FolderListItem 视图中。
public String getFolderName(Context context, int position) {
Cursor cursor = (Cursor) getItem(position);
return (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
}
+// 获取文件夹列表中某个位置的文件夹名称。
private class FolderListItem extends LinearLayout {
private TextView mName;
@@ -76,5 +79,7 @@ public class FoldersListAdapter extends CursorAdapter {
mName.setText(name);
}
}
+// FolderListItem 类是一个自定义的 LinearLayout,用于显示文件夹列表项的布局。它包含一个 TextView 控件,用于显示文件夹名称。
}
+//这段代码是一个自定义的 CursorAdapter 类 FoldersListAdapter,用于在 Android 应用程序中显示一个文件夹列表。
diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java b/src/Notes/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java
index 387c03a..83139d1 100644
--- a/src/Notes/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java
+++ b/src/Notes/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java
@@ -84,8 +84,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
public ImageView ibSetBgColor;
}
+// HeadViewHolder类定义了一组视图,用于在列表或网格中显示信息。这些视图包括一个TextView用于显示修改信息,一个ImageView用于显示警报图标,另一个TextView用于显示警报日期,还有一个ImageView用于选择背景颜色。
private static final Map sBgSelectorBtnsMap = new HashMap();
+
static {
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
sBgSelectorBtnsMap.put(R.id.iv_bg_red, ResourceParser.RED);
@@ -95,6 +97,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private static final Map sBgSelectorSelectionMap = new HashMap();
+
static {
sBgSelectorSelectionMap.put(ResourceParser.YELLOW, R.id.iv_bg_yellow_select);
sBgSelectorSelectionMap.put(ResourceParser.RED, R.id.iv_bg_red_select);
@@ -102,8 +105,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sBgSelectorSelectionMap.put(ResourceParser.GREEN, R.id.iv_bg_green_select);
sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select);
}
+// sBgSelectorBtnsMap是一个HashMap,将用于选择背景颜色的ImageView视图的资源ID映射到整数值,这些整数值在ResourceParser类中定义。同样,sBgSelectorSelectionMap将整数值映射到所选ImageView视图的资源ID。
private static final Map sFontSizeBtnsMap = new HashMap();
+
static {
sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE);
sFontSizeBtnsMap.put(R.id.ll_font_small, ResourceParser.TEXT_SMALL);
@@ -112,12 +117,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private static final Map sFontSelectorSelectionMap = new HashMap();
+
static {
sFontSelectorSelectionMap.put(ResourceParser.TEXT_LARGE, R.id.iv_large_select);
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SMALL, R.id.iv_small_select);
sFontSelectorSelectionMap.put(ResourceParser.TEXT_MEDIUM, R.id.iv_medium_select);
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SUPER, R.id.iv_super_select);
}
+// sFontSizeBtnsMap将用于选择字体大小的LinearLayout视图的资源ID映射到整数值,而sFontSelectorSelectionMap将整数值映射到所选ImageView视图的资源ID。
private static final String TAG = "NoteEditActivity";
@@ -185,10 +192,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* If the user specified the {@link Intent#ACTION_VIEW} but not provided with id,
* then jump to the NotesListActivity
*/
- mWorkingNote = null;
+// 果用户指定了 Intent.ACTION_VIEW 动作但没有提供ID,则跳转到 NotesListActivity
+ mWorkingNote = null;//在方法中,首先将mWorkingNote设置为null。然后,根据传入的Intent的动作(action)进行选择。
if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) {
+// Intent中获取笔记ID
long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0);
+ // 将用户查询字符串设置为空
mUserQuery = "";
+ // 如果Intent包含了搜索结果的额外数据,则从额外数据中获取笔记ID,并将用户查询字符串设置为搜索管理器中的用户查询字符串
/**
* Starting from the searched result
@@ -198,6 +209,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY);
}
+ // 如果笔记在笔记数据库中不存在,则跳转到 NotesListActivity 并显示错误信息的Toast,最后结束 Activity 并返回 false
if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) {
Intent jump = new Intent(this, NotesListActivity.class);
startActivity(jump);
@@ -205,6 +217,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
finish();
return false;
} else {
+ // 加载笔记
mWorkingNote = WorkingNote.load(this, noteId);
if (mWorkingNote == null) {
Log.e(TAG, "load note failed with note id" + noteId);
@@ -212,11 +225,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return false;
}
}
+// 如果该Intent的动作(action)为Intent.ACTION_VIEW,则从该Intent中获取笔记的ID(noteId)。如果该Intent还包含了一个搜索结果(Search)的额外数据(extra data key),则将noteId从额外数据中获取,并将用户查询字符串(mUserQuery)设置为搜索管理器中的用户查询字符串(SearchManager.USER_QUERY)。如果noteId在笔记数据库中不存在,则将Activity转到NotesListActivity,并显示一个错误信息的Toast,最后结束Activity并返回false。如果noteId在笔记数据库中存在,则加载该笔记的工作副本(mWorkingNote),如果加载失败,则结束Activity并返回false。
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
- } else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) {
- // New note
+ } else if (TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) {
+ // New note 如果用户指定了 Intent.ACTION_INSERT_OR_EDIT 动作,则获取笔记ID,如果笔记ID存在,则加载笔记,否则,创建一个新的笔记
long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0);
int widgetId = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
@@ -270,20 +284,26 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private void initNoteScreen() {
+ // 使用mFontSizeId设置笔记编辑器的文本外观。
mNoteEditor.setTextAppearance(this, TextAppearanceResources
.getTexAppearanceResource(mFontSizeId));
+ // 如果mWorkingNote的CheckListMode为TextNote.MODE_CHECK_LIST,则将编辑器转换为列表模式。
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
switchToListMode(mWorkingNote.getContent());
} else {
+ // 如果mWorkingNote的CheckListMode不是TextNote.MODE_CHECK_LIST,则在编辑器中显示笔记内容,并使用mUserQuery高亮显示查询结果。
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
mNoteEditor.setSelection(mNoteEditor.getText().length());
}
+ // 隐藏背景选择器中所有不在sBgSelectorSelectionMap中的ID的视图。
for (Integer id : sBgSelectorSelectionMap.keySet()) {
findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE);
}
+ // 设置mHeadViewPanel和mNoteEditorPanel的背景颜色为mWorkingNote的标题背景ID和背景颜色ID。
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
+ // 在标题栏中显示修改日期。
mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(this,
mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
| DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
@@ -297,6 +317,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private void showAlertHeader() {
+ // 如果mWorkingNote具有闹钟提醒,则检查当前时间是否超过提醒时间,如果超过,则在标题栏中显示“note_alert_expired”文本;否则,在标题栏中显示相对时间。
if (mWorkingNote.hasClockAlert()) {
long time = System.currentTimeMillis();
if (time > mWorkingNote.getAlertDate()) {
@@ -305,12 +326,15 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteHeaderHolder.tvAlertDate.setText(DateUtils.getRelativeTimeSpanString(
mWorkingNote.getAlertDate(), time, DateUtils.MINUTE_IN_MILLIS));
}
+ // 将标题栏中的提醒日期文本和提醒图标设置为可见。
mNoteHeaderHolder.tvAlertDate.setVisibility(View.VISIBLE);
mNoteHeaderHolder.ivAlertIcon.setVisibility(View.VISIBLE);
} else {
+ // 如果mWorkingNote没有闹钟提醒,则将标题栏中的提醒日期文本和提醒图标设置为不可见。
mNoteHeaderHolder.tvAlertDate.setVisibility(View.GONE);
mNoteHeaderHolder.ivAlertIcon.setVisibility(View.GONE);
- };
+ }
+ ;
}
@Override
@@ -322,7 +346,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- /**
+ /*
* For new note without note id, we should firstly save it to
* generate a id. If the editing note is not worth saving, there
* is no id which is equivalent to create new note
@@ -336,31 +360,36 @@ public class NoteEditActivity extends Activity implements OnClickListener,
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
+ // 如果笔记背景颜色选择器可见,并且触摸事件不在笔记背景颜色选择器范围内,则隐藏笔记背景颜色选择器并返回true。
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE
&& !inRangeOfView(mNoteBgColorSelector, ev)) {
mNoteBgColorSelector.setVisibility(View.GONE);
return true;
}
+ // 如果字体大小选择器可见,并且触摸事件不在字体大小选择器范围内,则隐藏字体大小选择器并返回true。
if (mFontSizeSelector.getVisibility() == View.VISIBLE
&& !inRangeOfView(mFontSizeSelector, ev)) {
mFontSizeSelector.setVisibility(View.GONE);
return true;
}
+ // 返回父类的dispatchTouchEvent方法。
return super.dispatchTouchEvent(ev);
}
private boolean inRangeOfView(View view, MotionEvent ev) {
- int []location = new int[2];
+ // 获取视图在屏幕上的位置。
+ int[] location = new int[2];
view.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
+ // 如果触摸事件的x坐标小于视图的x坐标、大于视图的宽度和x坐标之和、y坐标小于视图的y坐标、或大于视图的高度和y坐标之和,则返回false,否则返回true。
if (ev.getX() < x
|| ev.getX() > (x + view.getWidth())
|| ev.getY() < y
|| ev.getY() > (y + view.getHeight())) {
- return false;
- }
+ return false;
+ }
return true;
}
@@ -384,15 +413,16 @@ public class NoteEditActivity extends Activity implements OnClickListener,
for (int id : sFontSizeBtnsMap.keySet()) {
View view = findViewById(id);
view.setOnClickListener(this);
- };
+ }
+ ;
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
mFontSizeId = mSharedPrefs.getInt(PREFERENCE_FONT_SIZE, ResourceParser.BG_DEFAULT_FONT_SIZE);
- /**
+ /*
* HACKME: Fix bug of store the resource id in shared preference.
* The id may larger than the length of resources, in this case,
* return the {@link ResourceParser#BG_DEFAULT_FONT_SIZE}
*/
- if(mFontSizeId >= TextAppearanceResources.getResourcesSize()) {
+ if (mFontSizeId >= TextAppearanceResources.getResourcesSize()) {
mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE;
}
mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
@@ -401,39 +431,40 @@ public class NoteEditActivity extends Activity implements OnClickListener,
@Override
protected void onPause() {
super.onPause();
- if(saveNote()) {
+ if (saveNote()) {
Log.d(TAG, "Note data was saved with length:" + mWorkingNote.getContent().length());
}
clearSettingState();
- }
+ }//onPause()方法在活动即将暂停时被调用。如果有任何更改,它会保存当前笔记,并清除任何设置状态。
private void updateWidget() {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) {
intent.setClass(this, NoteWidgetProvider_2x.class);
- } else if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_4X) {
- intent.setClass(this, NoteWidgetProvider_4x.class);
} else if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_3X) {
intent.setClass(this, NoteWidgetProvider_3x.class);
+ } else if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_4X) {
+ intent.setClass(this, NoteWidgetProvider_4x.class);
} else {
Log.e(TAG, "Unsupported widget type");
return;
}
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
- mWorkingNote.getWidgetId()
+ intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[]{
+ mWorkingNote.getWidgetId()
});
sendBroadcast(intent);
setResult(RESULT_OK, intent);
- }
+ }//updateWidget()方法更新与当前笔记相关联的小部件。它创建一个意图,并根据笔记的小部件类型设置相应的小部件提供程序类。然后它发送一个广播,带有小部件ID以更新小部件。
+
public void onClick(View v) {
int id = v.getId();
if (id == R.id.btn_set_bg_color) {
mNoteBgColorSelector.setVisibility(View.VISIBLE);
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
- View.VISIBLE);
+ -View.VISIBLE);
} else if (sBgSelectorBtnsMap.containsKey(id)) {
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.GONE);
@@ -453,17 +484,17 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
mFontSizeSelector.setVisibility(View.GONE);
}
- }
+ }//onClick()方法处理UI中各种按钮的点击事件。当单击相应的按钮时,它会显示颜色选择器或字体大小选择器。它还根据所选选项更新笔记的字体大小或背景颜色。
@Override
public void onBackPressed() {
- if(clearSettingState()) {
+ if (clearSettingState()) {
return;
}
saveNote();
super.onBackPressed();
- }
+ }//onBackPressed()方法在按下返回按钮时被调用。它检查当前是否有任何设置状态处于活动状态,并清除它。然后它保存当前笔记并调用超类实现。
private boolean clearSettingState() {
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE) {
@@ -474,14 +505,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return true;
}
return false;
- }
+ }//clearSettingState()方法检查当前是否有任何设置状态处于活动状态,并清除它。
public void onBackgroundColorChanged() {
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.VISIBLE);
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
- }
+ }//onBackgroundColorChanged()方法在选择新的背景颜色时被调用。它更新笔记的背景颜色,并更新颜色选择器的颜色。
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
@@ -506,7 +537,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
menu.findItem(R.id.menu_delete_remind).setVisible(false);
}
return true;
- }
+ }//onFontSizeChanged()方法在选择新的字体大小时被调用。它更新笔记的字体大小,并更新字体大小选择器的值。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
@@ -560,7 +591,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis());
d.setOnDateTimeSetListener(new OnDateTimeSetListener() {
public void OnDateTimeSet(AlertDialog dialog, long date) {
- mWorkingNote.setAlertDate(date , true);
+ mWorkingNote.setAlertDate(date, true);
}
});
d.show();
@@ -575,7 +606,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
intent.putExtra(Intent.EXTRA_TEXT, info);
intent.setType("text/plain");
context.startActivity(intent);
- }
+ }//sendTo(Context context, String info)方法创建一个新的意图,并使用Intent.EXTRA_TEXT将信息作为文本传递。它的目的是启动共享对话框,让用户分享笔记的内容。
+
private void createNewNote() {
// Firstly, save current editing notes
@@ -587,7 +619,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mWorkingNote.getFolderId());
startActivity(intent);
- }
+ }//createNewNote()方法保存当前正在编辑的笔记,然后启动一个新的NoteEditActivity以创建一个新的笔记。通过设置Intent.ACTION_INSERT_OR_EDIT和Notes.INTENT_EXTRA_FOLDER_ID,该方法指示NoteEditActivity启动以插入或编辑笔记,并指定所选文件夹的ID。
private void deleteCurrentNote() {
if (mWorkingNote.existInDatabase()) {
@@ -609,11 +641,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
}
mWorkingNote.markDeleted(true);
- }
+ }//deleteCurrentNote()方法删除当前笔记。如果该笔记已存储在数据库中,则将其从数据库中删除。如果应用程序处于同步模式下,则将其移动到垃圾文件夹中,而不是永久删除。无论是删除还是移动,该方法都会将当前笔记标记为已删除。
private boolean isSyncMode() {
return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
- }
+ }//isSyncMode()方法检查应用程序是否处于同步模式。如果已经选择了同步帐户,则返回true。否则,返回false。
public void onClockAlertChanged(long date, boolean set) {
/**
@@ -629,7 +661,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
AlarmManager alarmManager = ((AlarmManager) getSystemService(ALARM_SERVICE));
showAlertHeader();
- if(!set) {
+ if (!set) {
alarmManager.cancel(pendingIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent);
@@ -648,6 +680,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
public void onWidgetChanged() {
updateWidget();
}
+// onWidgetChanged()方法会在小部件更改时被调用。它会调用updateWidget()方法来更新小部件。
public void onEditTextDelete(int index, String text) {
int childCount = mEditTextList.getChildCount();
@@ -662,7 +695,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mEditTextList.removeViewAt(index);
NoteEditText edit = null;
- if(index == 0) {
+ if (index == 0) {
edit = (NoteEditText) mEditTextList.getChildAt(0).findViewById(
R.id.et_edit_text);
} else {
@@ -674,12 +707,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
edit.requestFocus();
edit.setSelection(length);
}
+// onEditTextDelete(int index, String text)方法会在删除NoteEditText视图时被调用。该方法首先检查是否只有一个NoteEditText视图存在,如果是则直接返回。然后,该方法会将所有后续视图的索引递减1。接下来,该方法会删除指定索引处的NoteEditText视图,并将其文本追加到前一个视图的文本中,以便将文本合并到一个视图中。最后,该方法将焦点设置在前一个视图中,并将光标移动到文本末尾。
public void onEditTextEnter(int index, String text) {
/**
* Should not happen, check for debug
*/
- if(index > mEditTextList.getChildCount()) {
+ if (index > mEditTextList.getChildCount()) {
Log.e(TAG, "Index out of mEditTextList boundrary, should not happen");
}
@@ -699,7 +733,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
String[] items = text.split("\n");
int index = 0;
for (String item : items) {
- if(!TextUtils.isEmpty(item)) {
+ if (!TextUtils.isEmpty(item)) {
mEditTextList.addView(getListItem(item, index));
index++;
}
@@ -710,6 +744,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteEditor.setVisibility(View.GONE);
mEditTextList.setVisibility(View.VISIBLE);
}
+// switchToListMode(String text)方法用于切换到清单模式。该方法首先清除所有视图,然后将文本根据换行符分隔为多个条目,并将每个条目添加到mEditTextList中。同时,该方法会添加一个新的空条目,以便用户可以在列表末尾添加新的条目。最后,该方法会将焦点设置在最后一个条目上,并将编辑器视图隐藏,将列表视图显示。
private Spannable getHighlightQueryResult(String fullText, String userQuery) {
SpannableString spannable = new SpannableString(fullText == null ? "" : fullText);
@@ -727,6 +762,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
return spannable;
}
+// getHighlightQueryResult(String fullText, String userQuery)方法用于标记在搜索查询中匹配的文本。该方法将返回一个Spannable对象,其中查询匹配的文本会被高亮显示。
private View getListItem(String item, int index) {
View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null);
@@ -758,18 +794,20 @@ public class NoteEditActivity extends Activity implements OnClickListener,
edit.setText(getHighlightQueryResult(item, mUserQuery));
return view;
}
+// getListItem(String item, int index)方法用于获取一个清单视图。该方法将从R.layout.note_edit_list_item文件中充气视图。在充气视图之后,该方法会将文本添加到NoteEditText视图中,并将复选框设置为选中或未选中状态。如果条目已选中,则文本将具有删除线。最后,该方法将返回该视图。
public void onTextChange(int index, boolean hasText) {
if (index >= mEditTextList.getChildCount()) {
Log.e(TAG, "Wrong index, should not happen");
return;
}
- if(hasText) {
+ if (hasText) {
mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.VISIBLE);
} else {
mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.GONE);
}
}
+// onTextChange(int index, boolean hasText)方法用于在清单视图中标记是否有文本。如果hasText为true,则将显示复选框;否则,将隐藏复选框。
public void onCheckListModeChanged(int oldMode, int newMode) {
if (newMode == TextNote.MODE_CHECK_LIST) {
@@ -784,6 +822,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteEditor.setVisibility(View.VISIBLE);
}
}
+// onCheckListModeChanged(int oldMode, int newMode)方法用于在清单模式和文本编辑模式之间切换。如果新模式为清单模式,则将文本转换为清单视图;否则,将清单视图转换为文本编辑视图。
private boolean getWorkingText() {
boolean hasChecked = false;
@@ -807,6 +846,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
return hasChecked;
}
+// getWorkingText()方法用于获取当前工作文本。如果当前模式为清单模式,则将所有条目合并为一个字符串,并添加检查框状态。否则,将返回当前编辑器文本。
private boolean saveNote() {
getWorkingText();
diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/NoteEditText.java b/src/Notes/app/src/main/java/net/micode/notes/ui/NoteEditText.java
index 2afe2a8..a4179e7 100644
--- a/src/Notes/app/src/main/java/net/micode/notes/ui/NoteEditText.java
+++ b/src/Notes/app/src/main/java/net/micode/notes/ui/NoteEditText.java
@@ -84,11 +84,11 @@ public class NoteEditText extends EditText {
public void setIndex(int index) {
mIndex = index;
- }
+ }//用于设置控件在父容器中的位置索引
public void setOnTextViewChangeListener(OnTextViewChangeListener listener) {
mOnTextViewChangeListener = listener;
- }
+ }//用于设置文本变化的监听器
public NoteEditText(Context context, AttributeSet attrs) {
super(context, attrs, android.R.attr.editTextStyle);
@@ -116,7 +116,7 @@ public class NoteEditText extends EditText {
int off = layout.getOffsetForHorizontal(line, x);
Selection.setSelection(getText(), off);
break;
- }
+ }//实现了点击控件后,将光标移动到点击位置的功能
return super.onTouchEvent(event);
}
@@ -166,6 +166,7 @@ public class NoteEditText extends EditText {
}
return super.onKeyUp(keyCode, event);
}
+// onKeyDown和onKeyUp方法实现了按下和松开键盘按键时的响应。
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
@@ -177,7 +178,7 @@ public class NoteEditText extends EditText {
}
}
super.onFocusChanged(focused, direction, previouslyFocusedRect);
- }
+ }//控件获得或失去焦点时触发,将焦点状态通知给监听器。
@Override
protected void onCreateContextMenu(ContextMenu menu) {
@@ -214,4 +215,5 @@ public class NoteEditText extends EditText {
}
super.onCreateContextMenu(menu);
}
+// 创建上下文菜单,当用户长按控件中的链接时,根据链接的协议类型创建不同的菜单项,点击菜单项后跳转到相应的链接。
}
diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListActivity.java b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListActivity.java
index c00449e..d059a71 100644
--- a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListActivity.java
+++ b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListActivity.java
@@ -82,7 +82,7 @@ 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;
@@ -94,7 +94,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private enum ListEditState {
NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER
- };
+ }
+
+ ;
private ListEditState mState;
@@ -134,7 +136,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
+ 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
protected void onCreate(Bundle savedInstanceState) {
@@ -142,7 +144,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
setContentView(R.layout.note_list);
initResources();
- /*
+ /**
* Insert an introduction when user firstly use this application
*/
setAppInfoFromRawRes();
@@ -157,18 +159,20 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
super.onActivityResult(requestCode, resultCode, data);
}
}
+// 这个方法重写了Activity类的onActivityResult()方法。当startActivityForResult()启动的活动结束时,它会被调用。它检查结果是否为RESULT_OK并且请求了REQUEST_CODE_OPEN_NODE或REQUEST_CODE_NEW_NODE。如果是,则通过调用changeCursor(null)更新笔记列表适配器。否则,它调用超类实现的onActivityResult()方法。
private void setAppInfoFromRawRes() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) {
+ // 从raw资源中读取介绍文件
StringBuilder sb = new StringBuilder();
InputStream in = null;
try {
- in = getResources().openRawResource(R.raw.introduction);
+ in = getResources().openRawResource(R.raw.introduction);
if (in != null) {
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
- char [] buf = new char[1024];
+ char[] buf = new char[1024];
int len = 0;
while ((len = br.read(buf)) > 0) {
sb.append(buf, 0, len);
@@ -181,7 +185,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
e.printStackTrace();
return;
} finally {
- if(in != null) {
+ if (in != null) {
try {
in.close();
} catch (IOException e) {
@@ -203,6 +207,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
}
+// 这个方法从一个原始的资源文件中读取介绍文件,并将其内容添加到应用程序的SharedPreferences中。如果介绍文件尚未被添加到SharedPreferences中,它将被添加,并设置一个标志表示文件已被添加。在此之后,每次启动应用程序时,它将不再读取介绍文件。
@Override
protected void onStart() {
@@ -259,7 +264,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mDropDownMenu = new DropdownMenu(NotesListActivity.this,
(Button) customView.findViewById(R.id.selection_menu),
R.menu.note_list_dropdown);
- mDropDownMenu.setOnDropdownMenuItemClickListener(new PopupMenu.OnMenuItemClickListener(){
+ mDropDownMenu.setOnDropdownMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
mNotesListAdapter.selectAll(!mNotesListAdapter.isAllSelected());
updateMenu();
@@ -269,6 +274,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
});
return true;
}
+// 这是Activity的onCreate()方法,它在创建活动时被调用。它设置了视图并调用了setAppInfoFromRawRes()和initNoteListView()方法以初始化应用程序。
private void updateMenu() {
int selectedCount = mNotesListAdapter.getSelectedCount();
@@ -285,33 +291,33 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
item.setTitle(R.string.menu_select_all);
}
}
- }
+ }//更新下拉菜单中的选项。该方法首先获取当前选中的笔记数量,然后格式化菜单标题,更新下拉菜单的标题,并更新菜单项的状态。
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
- }
+ }//准备操作模式。该方法在操作模式即将被启动时调用,并返回一个布尔值,指示是否应该启动操作模式。
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// TODO Auto-generated method stub
return false;
- }
+ }//处理操作模式中的菜单项点击事件。该方法在用户点击操作模式中的菜单项时调用,并返回一个布尔值,指示是否已经处理了该事件。
public void onDestroyActionMode(ActionMode mode) {
mNotesListAdapter.setChoiceMode(false);
mNotesListView.setLongClickable(true);
mAddNewNote.setVisibility(View.VISIBLE);
- }
+ }//销毁操作模式。该方法在操作模式被销毁时调用,并将列表适配器的选择模式设置为false,将列表项的长按功能重新启用,并显示添加新笔记的按钮。
public void finishActionMode() {
mActionMode.finish();
- }
+ }//结束操作模式。该方法结束操作模式。
public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
- boolean checked) {
+ boolean checked) {
mNotesListAdapter.setCheckedItem(position, checked);
updateMenu();
- }
+ }//当用户选中或取消选中一个列表项时调用。该方法更新适配器中对应列表项的选中状态,并调用updateMenu()方法更新下拉菜单中的选项。
public boolean onMenuItemClick(MenuItem item) {
if (mNotesListAdapter.getSelectedCount() == 0) {
@@ -326,14 +332,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
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()));
+ mNotesListAdapter.getSelectedCount()));
builder.setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog,
- int which) {
- batchDelete();
- }
- });
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int which) {
+ batchDelete();
+ }
+ });
builder.setNegativeButton(android.R.string.cancel, null);
builder.show();
break;
@@ -345,6 +351,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
return true;
}
+// 处理下拉菜单中的菜单项点击事件。该方法在用户点击下拉菜单中的菜单项时调用,并根据菜单项的ID执行相应的操作。如果成功处理了菜单项,则返回true,否则返回false。如果没有选中任何笔记,则显示一个Toast提示用户需要先选择笔记。如果选择了“删除”菜单项,则弹出一个对话框,询问用户是否确定要删除所选笔记。如果选择了“移动”菜单项,则启动查询目标文件夹的操作。
}
private class NewNoteOnTouchListener implements OnTouchListener {
@@ -407,32 +414,40 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return false;
}
- };
+ }
+
+ ;
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)
+ Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[]{
+ String.valueOf(mCurrentFolderId)
}, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
}
+ // 后台查询处理程序,继承自AsyncQueryHandler
private final class BackgroundQueryHandler extends AsyncQueryHandler {
public BackgroundQueryHandler(ContentResolver contentResolver) {
super(contentResolver);
}
+// 构造函数,调用父类AsyncQueryHandler的构造函数
+ // 查询完成后的回调函数,根据token值进行不同的处理
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
switch (token) {
case FOLDER_NOTE_LIST_QUERY_TOKEN:
+ // 更新列表Adapter的Cursor
mNotesListAdapter.changeCursor(cursor);
break;
case FOLDER_LIST_QUERY_TOKEN:
if (cursor != null && cursor.getCount() > 0) {
+ // 显示文件夹列表菜单
showFolderListMenu(cursor);
} else {
+ // 查询文件夹失败,输出错误信息
Log.e(TAG, "Query folder failed");
}
break;
@@ -442,35 +457,48 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
+ // 显示文件夹列表菜单
private void showFolderListMenu(Cursor cursor) {
+ // 创建AlertDialog.Builder
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
builder.setTitle(R.string.menu_title_select_folder);
+ // 创建文件夹列表的Adapter
final FoldersListAdapter adapter = new FoldersListAdapter(this, cursor);
+ // 设置Adapter和点击事件
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
+ // 批量移动选中的笔记到指定文件夹
DataUtils.batchMoveToFolder(mContentResolver,
mNotesListAdapter.getSelectedItemIds(), adapter.getItemId(which));
+ // 显示移动笔记的提示信息
Toast.makeText(
NotesListActivity.this,
getString(R.string.format_move_notes_to_folder,
mNotesListAdapter.getSelectedCount(),
adapter.getFolderName(NotesListActivity.this, which)),
Toast.LENGTH_SHORT).show();
+ // 结束ActionMode
mModeCallBack.finishActionMode();
}
});
+ // 显示AlertDialog
builder.show();
}
+ // 创建新笔记
private void createNewNote() {
+ // 创建Intent,跳转到NoteEditActivity
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mCurrentFolderId);
+ // 启动ActivityForResult
this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE);
}
+ // 批量删除选中的笔记
private void batchDelete() {
+ // 创建异步任务
new AsyncTask>() {
protected HashSet doInBackground(Void... unused) {
HashSet widgets = mNotesListAdapter.getSelectedWidget();
@@ -534,47 +562,52 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
+ // 打开笔记详情页
private void openNode(NoteItemData data) {
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_VIEW);
- intent.putExtra(Intent.EXTRA_UID, data.getId());
- this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE);
+ intent.putExtra(Intent.EXTRA_UID, data.getId());// 将笔记的id作为参数传递给NoteEditActivity
+ this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE);// 启动NoteEditActivity,并等待返回结果
}
+ // 打开文件夹
private void openFolder(NoteItemData data) {
- mCurrentFolderId = data.getId();
- startAsyncNotesListQuery();
- if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
- mState = ListEditState.CALL_RECORD_FOLDER;
- mAddNewNote.setVisibility(View.GONE);
+ mCurrentFolderId = data.getId();// 将当前文件夹的id保存到成员变量mCurrentFolderId
+ startAsyncNotesListQuery();// 异步查询当前文件夹下的笔记列表
+ if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {// 如果打开的是CallRecord文件夹
+ mState = ListEditState.CALL_RECORD_FOLDER;// 设置状态为CALL_RECORD_FOLDER
+ mAddNewNote.setVisibility(View.GONE);// 隐藏新建笔记按钮
} else {
- mState = ListEditState.SUB_FOLDER;
+ mState = ListEditState.SUB_FOLDER;// 设置状态为SUB_FOLDER
}
- if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
- mTitleBar.setText(R.string.call_record_folder_name);
+ if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {// 如果打开的是CallRecord文件夹
+ mTitleBar.setText(R.string.call_record_folder_name);// 将标题栏文本设置为"通话录音"
} else {
- mTitleBar.setText(data.getSnippet());
+ mTitleBar.setText(data.getSnippet());// 将标题栏文本设置为当前文件夹的名字
}
- mTitleBar.setVisibility(View.VISIBLE);
+ mTitleBar.setVisibility(View.VISIBLE); // 显示标题栏
}
+ // 按钮点击事件
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_new_note:
- createNewNote();
+ createNewNote();// 创建新笔记
break;
default:
break;
}
}
+ // 显示软键盘
private void showSoftInput() {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (inputMethodManager != null) {
- inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
+ inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); // 显示软键盘
}
}
+ // 隐藏软键盘
private void hideSoftInput(View view) {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
@@ -606,7 +639,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
});
final Dialog dialog = builder.setView(view).show();
- final Button positive = (Button)dialog.findViewById(android.R.id.button1);
+ final Button positive = (Button) dialog.findViewById(android.R.id.button1);
positive.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
hideSoftInput(etName);
@@ -624,8 +657,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
values.put(NoteColumns.LOCAL_MODIFIED, 1);
mContentResolver.update(Notes.CONTENT_NOTE_URI, values, NoteColumns.ID
- + "=?", new String[] {
- String.valueOf(mFocusNoteDataItem.getId())
+ + "=?", new String[]{
+ String.valueOf(mFocusNoteDataItem.getId())
});
}
} else if (!TextUtils.isEmpty(name)) {
@@ -663,7 +696,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
});
- }
+ }//用于显示一个对话框,让用户输入或修改一个文件夹的名称。
@Override
public void onBackPressed() {
@@ -688,27 +721,29 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
break;
}
}
+// 重写返回键的行为,根据当前的状态执行不同的操作,如返回到上一级文件夹、返回到笔记列表、或者直接退出应用程序。
private void updateWidget(int appWidgetId, int appWidgetType) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
if (appWidgetType == Notes.TYPE_WIDGET_2X) {
intent.setClass(this, NoteWidgetProvider_2x.class);
- } else if (appWidgetType == Notes.TYPE_WIDGET_4X) {
- intent.setClass(this, NoteWidgetProvider_4x.class);
} else if (appWidgetType == Notes.TYPE_WIDGET_3X) {
intent.setClass(this, NoteWidgetProvider_3x.class);
+ } else if (appWidgetType == Notes.TYPE_WIDGET_4X) {
+ intent.setClass(this, NoteWidgetProvider_4x.class);
} else {
- Log.e(TAG, "Unspported widget type");
+ Log.e(TAG, "Unsupported widget type");
return;
}
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
- appWidgetId
+ intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[]{
+ appWidgetId
});
sendBroadcast(intent);
setResult(RESULT_OK, intent);
}
+// 更新小部件的方法,根据小部件的类型选择不同的小部件提供者,并发送广播更新小部件。
private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener() {
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
@@ -720,6 +755,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
};
+// 长按文件夹时创建上下文菜单的监听器,菜单包括查看文件夹、删除文件夹和修改文件夹名称等选项。
@Override
public void onContextMenuClosed(Menu menu) {
@@ -728,6 +764,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
super.onContextMenuClosed(menu);
}
+// 上下文菜单关闭时的操作,将监听器设为null。
@Override
public boolean onContextItemSelected(MenuItem item) {
@@ -762,6 +799,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
+// 选择上下文菜单选项时的操作,根据所选选项执行不同的操作,如打开文件夹、删除文件夹或修改文件夹名称。
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
@@ -780,6 +818,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
return true;
}
+// 准备选项菜单时的操作,根据当前的状态显示不同的菜单选项,如笔记列表、子文件夹或通话记录文件夹。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
@@ -820,6 +859,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
return true;
}
+// 选择选项菜单选项时的操作,根据所选选项执行不同的操作,如打开笔记列表、打开子文件夹或打开通话记录文件夹。
@Override
public boolean onSearchRequested() {
@@ -872,12 +912,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private boolean isSyncMode() {
return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
}
+// ,表示当前是否处于同步模式。它通过调用 NotesPreferenceActivity.getSyncAccountName(this) 获取同步账户名,并检查它的长度是否大于 0 来确定是否启用同步模式。
private void startPreferenceActivity() {
Activity from = getParent() != null ? getParent() : this;
Intent intent = new Intent(from, NotesPreferenceActivity.class);
from.startActivityIfNeeded(intent, -1);
}
+// 方法启动设置活动,它创建一个 Intent 对象并使用当前活动作为上下文调用 startActivityIfNeeded() 方法来启动设置活动。如果当前活动已经是设置活动的父级,则使用 getParent() 方法获取父级活动。
private class OnListItemClickListener implements OnItemClickListener {
@@ -919,24 +961,26 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
+// OnListItemClickListener 是一个内部类,实现了 OnItemClickListener 接口。它覆盖了 onItemClick() 方法,在列表项被单击时执行一系列操作。首先,它检查当前是否处于选择模式。如果是,则根据列表项的类型执行不同的操作。如果不是,则根据当前状态执行不同的操作,如打开文件夹或笔记。
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 + ")";
+ 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[] {
+ new String[]{
String.valueOf(Notes.TYPE_FOLDER),
String.valueOf(Notes.ID_TRASH_FOLER),
String.valueOf(mCurrentFolderId)
},
NoteColumns.MODIFIED_DATE + " DESC");
}
+// 启动后台查询,以获取目标文件夹列表。它构建一个查询选择器,通过调用 mBackgroundQueryHandler.startQuery() 方法执行查询操作。查询的结果将被传递到 FoldersListAdapter 中进行处理。
public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
if (view instanceof NotesListItem) {
@@ -954,4 +998,5 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
return false;
}
+// 在列表项被长按时执行。它首先获取当前长按的列表项,并将其类型存储在 mFocusNoteDataItem 中。如果类型为笔记且不在选择模式下,则启动上下文操作模式,并将当前列表项标记为已选中。如果类型为文件夹,则设置上下文菜单的创建监听器。
}
diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java
index 51c9cb9..18f72ef 100644
--- a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java
+++ b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java
@@ -53,7 +53,7 @@ public class NotesListAdapter extends CursorAdapter {
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return new NotesListItem(context);
- }
+ }//创建一个新的笔记列表项视图,即 NotesListItem。
@Override
public void bindView(View view, Context context, Cursor cursor) {
@@ -62,21 +62,21 @@ public class NotesListAdapter extends CursorAdapter {
((NotesListItem) view).bind(context, itemData, mChoiceMode,
isSelectedItem(cursor.getPosition()));
}
- }
+ }//将笔记数据绑定到给定的笔记列表项视图中。
public void setCheckedItem(final int position, final boolean checked) {
mSelectedIndex.put(position, checked);
notifyDataSetChanged();
- }
+ }//设置给定位置的笔记是否被选中,并通知适配器数据已更改。
public boolean isInChoiceMode() {
return mChoiceMode;
- }
+ }//返回是否处于选择笔记的模式。
public void setChoiceMode(boolean mode) {
mSelectedIndex.clear();
mChoiceMode = mode;
- }
+ }//设置选择笔记的模式,并清空 mSelectedIndex。
public void selectAll(boolean checked) {
Cursor cursor = getCursor();
@@ -87,7 +87,7 @@ public class NotesListAdapter extends CursorAdapter {
}
}
}
- }
+ }//选择所有笔记。
public HashSet getSelectedItemIds() {
HashSet itemSet = new HashSet();
@@ -103,7 +103,8 @@ public class NotesListAdapter extends CursorAdapter {
}
return itemSet;
- }
+ }//返回选定的笔记的 ID。
+
public HashSet getSelectedWidget() {
HashSet itemSet = new HashSet();
@@ -126,7 +127,7 @@ public class NotesListAdapter extends CursorAdapter {
}
}
return itemSet;
- }
+ }//返回选定的小部件信息。
public int getSelectedCount() {
Collection values = mSelectedIndex.values();
@@ -141,31 +142,31 @@ public class NotesListAdapter extends CursorAdapter {
}
}
return count;
- }
+ }//返回选定笔记的数量。
public boolean isAllSelected() {
int checkedCount = getSelectedCount();
return (checkedCount != 0 && checkedCount == mNotesCount);
- }
+ }//返回是否已经选择了所有笔记。
public boolean isSelectedItem(final int position) {
if (null == mSelectedIndex.get(position)) {
return false;
}
return mSelectedIndex.get(position);
- }
+ }//返回给定位置的笔记是否被选中。
@Override
protected void onContentChanged() {
super.onContentChanged();
calcNotesCount();
- }
+ }//当笔记数据发生变化时,重新计算笔记数量。
@Override
public void changeCursor(Cursor cursor) {
super.changeCursor(cursor);
calcNotesCount();
- }
+ }//更改笔记数据游标时,重新计算笔记数量。
private void calcNotesCount() {
mNotesCount = 0;
@@ -180,5 +181,5 @@ public class NotesListAdapter extends CursorAdapter {
return;
}
}
- }
+ }//计算笔记数量。
}
diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListItem.java b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListItem.java
index 1221e80..147c4ea 100644
--- a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListItem.java
+++ b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListItem.java
@@ -98,6 +98,7 @@ public class NotesListItem extends LinearLayout {
setBackground(data);
}
+ // 用于将数据绑定到视图的UI组件上,它接受一个NoteItemData对象,其中包含有关笔记项的信息,以及两个布尔标志:choiceMode和checked。
private void setBackground(NoteItemData data) {
int id = data.getBgColorId();
diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java
index 07c5f7e..ed4d6af 100644
--- a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java
+++ b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java
@@ -86,7 +86,7 @@ public class NotesPreferenceActivity extends PreferenceActivity {
mOriAccounts = null;
View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null);
getListView().addHeaderView(header, null, true);
- }
+ }//当创建Activity时调用。在此方法中,ActionBar的返回按钮启用,加载应用程序的偏好设置,注册广播接收器,添加一个标题视图。
@Override
protected void onResume() {
@@ -114,7 +114,7 @@ public class NotesPreferenceActivity extends PreferenceActivity {
}
refreshUI();
- }
+ }//当Activity从暂停状态恢复时调用。在此方法中,检查用户是否已添加了新帐户,如果是,则需要自动设置同步帐户。
@Override
protected void onDestroy() {
@@ -122,7 +122,7 @@ public class NotesPreferenceActivity extends PreferenceActivity {
unregisterReceiver(mReceiver);
}
super.onDestroy();
- }
+ }//当Activity被销毁时调用。在此方法中,注销广播接收器。
private void loadAccountPreference() {
mAccountCategory.removeAll();
@@ -152,7 +152,7 @@ public class NotesPreferenceActivity extends PreferenceActivity {
});
mAccountCategory.addPreference(accountPref);
- }
+ }//加载应用程序的帐户偏好设置,包括标题、摘要和单击事件监听器。
private void loadSyncButton() {
Button syncButton = (Button) findViewById(R.id.preference_sync_button);
@@ -191,12 +191,12 @@ public class NotesPreferenceActivity extends PreferenceActivity {
lastSyncTimeView.setVisibility(View.GONE);
}
}
- }
+ }//加载同步按钮和上次同步时间文本视图,并设置相应的单击事件监听器。
private void refreshUI() {
loadAccountPreference();
loadSyncButton();
- }
+ }//刷新用户界面,加载帐户偏好设置和同步按钮。
private void showSelectAccountAlertDialog() {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
@@ -252,7 +252,7 @@ public class NotesPreferenceActivity extends PreferenceActivity {
dialog.dismiss();
}
});
- }
+ }//弹出一个对话框,提示用户选择一个帐户进行同步。
private void showChangeAccountConfirmAlertDialog() {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
@@ -384,5 +384,5 @@ public class NotesPreferenceActivity extends PreferenceActivity {
default:
return false;
}
- }
+ }//当用户选择同步帐户时调用。在此方法中,更新同步按钮的文本视图,并启用同步按钮。
}
diff --git a/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_3x.java b/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_3x.java
index 9626f78..d7ddbd8 100644
--- a/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_3x.java
+++ b/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_3x.java
@@ -21,7 +21,7 @@ public class NoteWidgetProvider_3x extends NoteWidgetProvider{ // 3x3大小的
@Override // 重写窗口小部件中的获取资源ID函数
protected int getBgResourceId(int bgId) {
- return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId);
+ return ResourceParser.WidgetBgResources.getWidget3xBgResource(bgId);
}
@Override // 重写窗口小部件中的获取宽度类型函数
diff --git a/src/Notes/app/src/main/res/values-zh-rCN/strings.xml b/src/Notes/app/src/main/res/values-zh-rCN/strings.xml
index 09f75ed..b360297 100644
--- a/src/Notes/app/src/main/res/values-zh-rCN/strings.xml
+++ b/src/Notes/app/src/main/res/values-zh-rCN/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
便签
便签2x2
+ 便签3x3
便签4x4
没有关联内容,点击新建便签。
访客模式下,便签内容不可见
diff --git a/src/Notes/app/src/main/res/values-zh-rTW/strings.xml b/src/Notes/app/src/main/res/values-zh-rTW/strings.xml
index e29b79b..5eb467b 100644
--- a/src/Notes/app/src/main/res/values-zh-rTW/strings.xml
+++ b/src/Notes/app/src/main/res/values-zh-rTW/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
便簽
便簽2x2
+ 便簽3x3
便簽4x4
沒有關聯內容,點擊新建便簽。
訪客模式下,便籤內容不可見
diff --git a/src/Notes/app/src/main/res/values/strings.xml b/src/Notes/app/src/main/res/values/strings.xml
index 55df868..7d941bb 100644
--- a/src/Notes/app/src/main/res/values/strings.xml
+++ b/src/Notes/app/src/main/res/values/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
Notes
Notes 2x2
+ Notes 3x3
Notes 4x4
No associated note found, click to create associated note.
Privacy mode,can not see note content
diff --git a/src/Notes/app/src/main/res/xml/widget_3x_info.xml b/src/Notes/app/src/main/res/xml/widget_3x_info.xml
new file mode 100644
index 0000000..03936e4
--- /dev/null
+++ b/src/Notes/app/src/main/res/xml/widget_3x_info.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/src/Notes/build.gradle b/src/Notes/build.gradle
index cdb59e3..07f17b1 100644
--- a/src/Notes/build.gradle
+++ b/src/Notes/build.gradle
@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.4.2'
+ classpath 'com.android.tools.build:gradle:8.0.0'
}
}
diff --git a/src/Notes/gradle.properties b/src/Notes/gradle.properties
new file mode 100644
index 0000000..f82049a
--- /dev/null
+++ b/src/Notes/gradle.properties
@@ -0,0 +1,3 @@
+android.defaults.buildfeatures.buildconfig=true
+android.nonFinalResIds=false
+android.nonTransitiveRClass=false
\ No newline at end of file
diff --git a/src/Notes/gradle/wrapper/gradle-wrapper.properties b/src/Notes/gradle/wrapper/gradle-wrapper.properties
index 829fbb8..ff44dd1 100644
--- a/src/Notes/gradle/wrapper/gradle-wrapper.properties
+++ b/src/Notes/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Sun Apr 02 08:57:13 CST 2023
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME