From 6fa81173220bdf2d4a375912703a46f62ae5be7c Mon Sep 17 00:00:00 2001 From: ZhaoJie <207594601@qq.com> Date: Sat, 22 Apr 2023 22:04:35 +0800 Subject: [PATCH 1/7] 1 1 --- doc/1.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/1.txt diff --git a/doc/1.txt b/doc/1.txt new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/doc/1.txt @@ -0,0 +1 @@ +1 \ No newline at end of file From 6717e081de574f8abc2ca758b2adadbde88923b4 Mon Sep 17 00:00:00 2001 From: gexinghai <2874903098@qq.com> Date: Sun, 23 Apr 2023 17:56:17 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E6=95=B4=E7=90=86=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=A4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++- .idea/.gitignore | 3 --- .idea/modules.xml | 8 -------- .idea/vcs.xml | 6 ------ README.md | 2 -- doc/1.txt | 1 - ...米便签开源代码的泛读报告.docx | Bin 533798 -> 533840 bytes readme.md | 2 -- 8 files changed, 2 insertions(+), 23 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml delete mode 100644 README.md delete mode 100644 doc/1.txt delete mode 100644 readme.md diff --git a/.gitignore b/.gitignore index 28431d4..5bfdaf6 100644 --- a/.gitignore +++ b/.gitignore @@ -113,4 +113,5 @@ $RECYCLE.BIN/ *.ipr *.iws /src/Notes/app/.idea/ -/src/Notes/app/libs/ \ No newline at end of file +/src/Notes/app/libs/ +/.idea 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 deleted file mode 100644 index 4757b3d..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Notes - diff --git a/doc/1.txt b/doc/1.txt deleted file mode 100644 index 56a6051..0000000 --- a/doc/1.txt +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/doc/小米便签开源代码的泛读报告.docx b/doc/小米便签开源代码的泛读报告.docx index 2a5d45108dcb48e6f4e0b8d754c711347d4cab98..c33be626ec9682a6edb3a50ee3aef720bf0bc791 100644 GIT binary patch delta 16520 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�y#m@GVNumaSMj>$EwA`ii#&j+FWvva& zVGMlJYLd}xW!Cr8sg>nQgN3$rl8AB7Zn-h)YrMulmXU$%ZQZ9%=qj^2+xKDNsuKBz z;P=%Ua;=L-N%o9eS@`42lsxBi=kteHda1@N`ZnUW!Zxu4$Tz~j=xUk=?cOf!7Ekoj zae^E>^J)EicN?d`6CqR{Zrj$polWERr~GF~mS1%3g)?l~V?1!Zk;;?R{=v}Y1I{OE zo1Oz?`SM$DW)qv=-*?6;OR0T#Sab0EL2%3oyu)nEGs=IP$u(sVWbWya{%xT!0=CV% zJi`3uf^5MuLx~$zV_xgi+j_SVU9UjhV_DB>6R&`>nUMwHPIdnl+I*YfF>hxjpjQ4^ z;PrmxYY2aN$IRXNr-eCd&e$Aczx(vDzbE-cYWVg@0h6u&uHogm=C|TjL&3y;+hwfB ze(X2t_qv4ddo)>fQ7N+)5!DuRxUk4BFf^IAgNN6%FP;a!EuQOnO7?uu|5lvYgR{?3^U-ah#`Q7GiGxN+j#RgkyI6!>7uk<_h}=!9x>j zjxv(7Ww-S^R?2x7PijExFmunxn>P!Ijt57u6a0dz7B8u1(yhnWO)(WEe`{lX3)R%A z=z9hGo`r%!xE~V2*+nU&J*hQaNTa&b!J{Jd7C0MU@USOPV0{=~f?~Ljd1t)J&MnS4 z*9R*em-l8TyzFYKI4@6eR}3Xg_cq|P`p-UC-vrgf_0OyM8t{c2l%x}uqyzeIfVC#+ zfD2l-T5v)R>4eP>fVa*MK%}^Y(Ir9t8&IuuNzkxSpeSh^gfK#2&p2rwgfJ|i_-U1d zFlzsK=hGmFV0a+^^LnR=62Yi~Qm3U8!3co{rL7VDds8G0ff$Ah)Fw@w7={t=|8uW` zfSezIfuQ~~ivRBd1tI=7tER;f!w7(ir%e;X@PoRfA&|hxfIS$bX_5R}O-)ND`S%g| zv^f$OQBd(UZea;Qe2hHOT)HPFI>8`M-@z(yGW|_&`C@&dC4m TPm@MU0YeS7NAS;>4f1~gW|*37 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 - From c4fe645595060acd0031e277cf9628568ea0155a Mon Sep 17 00:00:00 2001 From: gexinghai <2874903098@qq.com> Date: Sun, 23 Apr 2023 17:59:31 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20READEME.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..2989e2d --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# 小米便签 + From 4874b422e41459b5ef8a35ead974293955473dd5 Mon Sep 17 00:00:00 2001 From: gexinghai <2874903098@qq.com> Date: Sun, 23 Apr 2023 18:00:19 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E5=88=A0=E9=99=A4=20.gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 117 ----------------------------------------------------- 1 file changed, 117 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 5bfdaf6..0000000 --- a/.gitignore +++ /dev/null @@ -1,117 +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/ -/.idea From 068b14af6df0dc37fc981ecf415d42e7b7ef4dd6 Mon Sep 17 00:00:00 2001 From: ZhaoJie <207594601@qq.com> Date: Tue, 25 Apr 2023 22:37:41 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E8=B5=B5=E6=9D=B0ui=E5=8C=85=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../micode/notes/ui/AlarmAlertActivity.java | 9 ++ .../micode/notes/ui/AlarmInitReceiver.java | 3 + .../net/micode/notes/ui/AlarmReceiver.java | 2 + .../net/micode/notes/ui/DateTimePicker.java | 45 ++++++++-- .../micode/notes/ui/DateTimePickerDialog.java | 4 + .../net/micode/notes/ui/DropdownMenu.java | 8 +- .../micode/notes/ui/FoldersListAdapter.java | 5 ++ .../net/micode/notes/ui/NoteEditActivity.java | 68 ++++++++++---- .../net/micode/notes/ui/NoteEditText.java | 10 ++- .../micode/notes/ui/NotesListActivity.java | 88 +++++++++++++------ .../net/micode/notes/ui/NotesListAdapter.java | 29 +++--- .../net/micode/notes/ui/NotesListItem.java | 1 + .../notes/ui/NotesPreferenceActivity.java | 16 ++-- 13 files changed, 211 insertions(+), 77 deletions(-) diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java b/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java index 85723be..280ae78 100644 --- a/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java @@ -60,6 +60,7 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); } +// 在Activity创建时被调用,它首先设置Activity的特性,然后获取传递过来的Intent,从中获取提醒的ID和摘录信息,并根据提醒的ID判断提醒是否可以在Note数据库中找到,并显示对应的提醒对话框和播放提醒声音。 Intent intent = getIntent(); @@ -82,11 +83,14 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD finish(); } } +// 以一个try-catch块开始,尝试从意图中提取一个笔记ID,使用笔记ID从内容提供程序中检索与该笔记相关的文本片段,并在文本片段太长时截断它。如果在此过程中抛出IllegalArgumentException异常,则捕获该异常并返回方法。 +//接下来的代码块创建一个新的MediaPlayer对象,并检查与笔记ID关联的笔记是否在笔记数据库中可见。如果可见,则调用名为showActionDialog()的方法,该方法可能显示一个对话框给用户。还调用了playAlarmSound()方法,该方法可能会播放警报声。如果笔记在数据库中不可见,则方法仅完成而不显示对话框或播放声音。 private boolean isScreenOn() { PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); return pm.isScreenOn(); } +// 用于判断屏幕是否打开。 private void playAlarmSound() { Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM); @@ -118,6 +122,7 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD e.printStackTrace(); } } +// 用于播放提醒声音,首先获取系统默认的闹铃铃声,然后判断当前是否为静音模式,如果是,则设置MediaPlayer的音频流类型为系统当前可影响铃声的流,否则设置为闹钟流类型。最后设置铃声数据源、循环播放并开始播放。 private void showActionDialog() { AlertDialog.Builder dialog = new AlertDialog.Builder(this); @@ -129,6 +134,7 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD } dialog.show().setOnDismissListener(this); } +// 用于显示提醒对话框,其中包含提醒的摘录信息和两个按钮(确认和进入)。 public void onClick(DialogInterface dialog, int which) { switch (which) { @@ -142,11 +148,13 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD break; } } +// 用于处理对话框中按钮的点击事件,如果是进入按钮,则启动NoteEditActivity并携带提醒的ID,将它作为Extra参数传递给NoteEditActivity以便打开对应的Note。如果是确认按钮,则什么都不做。 public void onDismiss(DialogInterface dialog) { stopAlarmSound(); finish(); } +// 用于处理提醒对话框关闭事件,停止播放提醒声音并结束Activity。 private void stopAlarmSound() { if (mPlayer != null) { @@ -156,3 +164,4 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD } } } +// 用于停止播放提醒声音。 diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java b/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java index f221202..5b41fe2 100644 --- a/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java @@ -28,6 +28,8 @@ import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; +//这里定义了一个包名为net.micode.notes.ui的Java类AlarmInitReceiver,它继承了BroadcastReceiver类。引入了Android系统提供的AlarmManager、PendingIntent、BroadcastReceiver、ContentUris等类。还引入了笔记相关的数据模型Notes和NoteColumns。 +//PROJECTION是笔记查询时的投影,指定了需要查询的列。COLUMN_ID和COLUMN_ALERTED_DATE则是笔记查询结果中对应的列索引。 public class AlarmInitReceiver extends BroadcastReceiver { private static final String [] PROJECTION = new String [] { @@ -62,4 +64,5 @@ public class AlarmInitReceiver extends BroadcastReceiver { c.close(); } } +// onReceive方法是接收广播后执行的方法。在这里,首先获取当前时间戳currentDate,然后通过getContentResolver().query方法查询所有需要提醒的笔记,查询条件是提醒时间大于当前时间戳并且类型是笔记类型。 } diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java b/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java index 54e503b..a485c43 100644 --- a/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java @@ -27,4 +27,6 @@ public class AlarmReceiver extends BroadcastReceiver { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } +// onReceive方法中,首先获取传入的Intent对象,并通过setClass方法将Intent的目标Activity设置为AlarmAlertActivity。然后通过addFlags方法设置Intent的标志位FLAG_ACTIVITY_NEW_TASK,表示启动一个新的Task来显示Activity。最后通过context.startActivity方法启动Activity。 } +//这段代码的作用是在系统闹钟触发时,启动AlarmAlertActivity来显示提醒内容。 \ No newline at end of file diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePicker.java b/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePicker.java index 496b0cd..9440fe4 100644 --- a/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePicker.java +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePicker.java @@ -67,9 +67,9 @@ public class DateTimePicker extends FrameLayout { private NumberPicker.OnValueChangeListener mOnDateChangedListener = new NumberPicker.OnValueChangeListener() { @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { - mDate.add(Calendar.DAY_OF_YEAR, newVal - oldVal); - updateDateControl(); - onDateTimeChanged(); + mDate.add(Calendar.DAY_OF_YEAR, newVal - oldVal);// 使用Calendar类的add方法将mDate对象的日期字段(即Calendar.DAY_OF_YEAR)增加newVal - oldVal天,以更新日期。 + updateDateControl();//调用updateDateControl方法,该方法用来更新日期控件的显示。 + onDateTimeChanged();//调用onDateTimeChanged方法,该方法用来通知其他组件该日期时间已经发生了变化。 } }; @@ -104,16 +104,20 @@ public class DateTimePicker extends FrameLayout { isDateChanged = true; } } +// 根据24小时制或12小时制以及上下午状态等情况,计算新的时间并更新到mDate字段中。 int newHour = mHourSpinner.getValue() % HOURS_IN_HALF_DAY + (mIsAm ? 0 : HOURS_IN_HALF_DAY); mDate.set(Calendar.HOUR_OF_DAY, newHour); onDateTimeChanged(); +// 调用onDateTimeChanged方法,该方法用来通知其他组件该日期时间已经发生了变化。 if (isDateChanged) { setCurrentYear(cal.get(Calendar.YEAR)); setCurrentMonth(cal.get(Calendar.MONTH)); setCurrentDay(cal.get(Calendar.DAY_OF_MONTH)); } +// 如果日期发生了变化,则调用setCurrentYear和setCurrentMonth方法更新年份和月份控件的显示。 } }; +// 这段代码定义了一个监听器对象,用于监听小时NumberPicker控件的值变化事件。 private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() { @Override @@ -126,6 +130,7 @@ public class DateTimePicker extends FrameLayout { } else if (oldVal == minValue && newVal == maxValue) { offset -= 1; } +// 当监听器被触发时,它首先根据 NumberPicker 的旧值和新值计算出一个 offset。如果旧值是最大值且新值是最小值,则将 offset 增加1。如果旧值是最小值且新值是最大值,则将 offset 减少1。 if (offset != 0) { mDate.add(Calendar.HOUR_OF_DAY, offset); mHourSpinner.setValue(getCurrentHour()); @@ -139,10 +144,13 @@ public class DateTimePicker extends FrameLayout { updateAmPmControl(); } } +// 如果 offset 不为0,则监听器会更新 mDate 变量,将 offset 添加到小时数中,将小时选择器的值设置为当前小时,调用 updateDateControl() 更新日期控件,并根据新的小时数更新 AM/PM 控件。 mDate.set(Calendar.MINUTE, newVal); onDateTimeChanged(); +// 更新 mDate 变量后,监听器将分钟值设置为新值,并调用 onDateTimeChanged() 通知任何监听器日期和时间已更新。 } }; +// 定义了一个私有字段 mOnMinuteChangedListener,它是 NumberPicker.OnValueChangeListener 的一个实例。当表示分钟的 NumberPicker 的值发生变化时,此监听器将被触发。 private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() { @Override @@ -156,12 +164,16 @@ public class DateTimePicker extends FrameLayout { updateAmPmControl(); onDateTimeChanged(); } +// 当监听器被触发时,它将 mIsAm 变量取反,表示用户选择了 AM 还是 PM。如果 mIsAm 是 true,则说明用户选择了 AM,此时监听器将 mDate 变量减去半天的小时数。如果 mIsAm 是 false,则说明用户选择了 PM,此时监听器将 mDate 变量加上半天的小时数。然后,监听器会调用 updateAmPmControl() 更新 AM/PM 控件,并调用 onDateTimeChanged() 通知任何监听器日期和时间已更新。 }; +// 定义了一个私有字段 mOnAmPmChangedListener,它是 NumberPicker.OnValueChangeListener 的一个实例。当表示 AM/PM 的 NumberPicker 的值发生变化时,此监听器将被触发。 public interface OnDateTimeChangedListener { void onDateTimeChanged(DateTimePicker view, int year, int month, int dayOfMonth, int hourOfDay, int minute); +// 该接口有一个抽象方法 onDateTimeChanged(),它在日期或时间发生变化时被调用。该方法接收 6 个参数:view 表示当前 DateTimePicker 实例,year 表示年份,month 表示月份(从 0 开始),dayOfMonth 表示月中的某一天,hourOfDay 表示小时数(24 小时制),minute 表示分钟数。 } +//定义了一个接口 OnDateTimeChangedListener,它用于监听日期和时间的变化。当日期或时间发生变化时,可以调用该接口的 onDateTimeChanged() 方法通知任何实现该接口的监听器。通过实现该接口并在需要的地方注册监听器,可以在日期或时间发生变化时执行自定义操作,例如更新 UI 或执行某些计算。 public DateTimePicker(Context context) { this(context, System.currentTimeMillis()); @@ -173,15 +185,18 @@ public class DateTimePicker extends FrameLayout { public DateTimePicker(Context context, long date, boolean is24HourView) { super(context); + mDate = Calendar.getInstance(); mInitialising = true; mIsAm = getCurrentHourOfDay() >= 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..93df003 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 @@ -63,7 +63,6 @@ import net.micode.notes.tool.ResourceParser.TextAppearanceResources; import net.micode.notes.ui.DateTimePickerDialog.OnDateTimeSetListener; import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener; import net.micode.notes.widget.NoteWidgetProvider_2x; -import net.micode.notes.widget.NoteWidgetProvider_3x; import net.micode.notes.widget.NoteWidgetProvider_4x; import java.util.HashMap; @@ -84,6 +83,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, public ImageView ibSetBgColor; } +// HeadViewHolder类定义了一组视图,用于在列表或网格中显示信息。这些视图包括一个TextView用于显示修改信息,一个ImageView用于显示警报图标,另一个TextView用于显示警报日期,还有一个ImageView用于选择背景颜色。 private static final Map sBgSelectorBtnsMap = new HashMap(); static { @@ -102,6 +102,7 @@ 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 { @@ -118,6 +119,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, 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 +187,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 +204,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 +212,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 +220,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 + // 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 +279,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 +312,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,9 +321,11 @@ 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); }; @@ -336,25 +354,30 @@ 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]; 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 @@ -405,7 +428,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, 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); @@ -413,10 +436,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, 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 { - Log.e(TAG, "Unsupported widget type"); + Log.e(TAG, "Unspported widget type"); return; } @@ -426,14 +447,16 @@ public class NoteEditActivity extends Activity implements OnClickListener, 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,7 +476,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, } mFontSizeSelector.setVisibility(View.GONE); } - } + }//onClick()方法处理UI中各种按钮的点击事件。当单击相应的按钮时,它会显示颜色选择器或字体大小选择器。它还根据所选选项更新笔记的字体大小或背景颜色。 @Override public void onBackPressed() { @@ -463,7 +486,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, saveNote(); super.onBackPressed(); - } + }//onBackPressed()方法在按下返回按钮时被调用。它检查当前是否有任何设置状态处于活动状态,并清除它。然后它保存当前笔记并调用超类实现。 private boolean clearSettingState() { if (mNoteBgColorSelector.getVisibility() == View.VISIBLE) { @@ -474,14 +497,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 +529,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) { @@ -575,7 +598,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 +611,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 +633,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) { /** @@ -648,6 +672,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(); @@ -674,6 +699,7 @@ 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) { /** @@ -710,6 +736,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 +754,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,6 +786,7 @@ 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()) { @@ -770,6 +799,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, 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 +814,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 +838,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..4d980ad 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 @@ -70,7 +70,6 @@ import net.micode.notes.tool.DataUtils; import net.micode.notes.tool.ResourceParser; import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute; import net.micode.notes.widget.NoteWidgetProvider_2x; -import net.micode.notes.widget.NoteWidgetProvider_3x; import net.micode.notes.widget.NoteWidgetProvider_4x; import java.io.BufferedReader; @@ -142,7 +141,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,10 +156,12 @@ 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 { @@ -203,6 +204,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt } } } +// 这个方法从一个原始的资源文件中读取介绍文件,并将其内容添加到应用程序的SharedPreferences中。如果介绍文件尚未被添加到SharedPreferences中,它将被添加,并设置一个标志表示文件已被添加。在此之后,每次启动应用程序时,它将不再读取介绍文件。 @Override protected void onStart() { @@ -269,6 +271,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt }); return true; } +// 这是Activity的onCreate()方法,它在创建活动时被调用。它设置了视图并调用了setAppInfoFromRawRes()和initNoteListView()方法以初始化应用程序。 private void updateMenu() { int selectedCount = mNotesListAdapter.getSelectedCount(); @@ -285,33 +288,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) { mNotesListAdapter.setCheckedItem(position, checked); updateMenu(); - } + }//当用户选中或取消选中一个列表项时调用。该方法更新适配器中对应列表项的选中状态,并调用updateMenu()方法更新下拉菜单中的选项。 public boolean onMenuItemClick(MenuItem item) { if (mNotesListAdapter.getSelectedCount() == 0) { @@ -345,6 +348,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt } return true; } +// 处理下拉菜单中的菜单项点击事件。该方法在用户点击下拉菜单中的菜单项时调用,并根据菜单项的ID执行相应的操作。如果成功处理了菜单项,则返回true,否则返回false。如果没有选中任何笔记,则显示一个Toast提示用户需要先选择笔记。如果选择了“删除”菜单项,则弹出一个对话框,询问用户是否确定要删除所选笔记。如果选择了“移动”菜单项,则启动查询目标文件夹的操作。 } private class NewNoteOnTouchListener implements OnTouchListener { @@ -418,21 +422,27 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt }, 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 +452,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 +557,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); @@ -663,7 +691,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt } }); - } + }//用于显示一个对话框,让用户输入或修改一个文件夹的名称。 @Override public void onBackPressed() { @@ -688,6 +716,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt break; } } +// 重写返回键的行为,根据当前的状态执行不同的操作,如返回到上一级文件夹、返回到笔记列表、或者直接退出应用程序。 private void updateWidget(int appWidgetId, int appWidgetType) { Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); @@ -695,8 +724,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt 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 { Log.e(TAG, "Unspported widget type"); return; @@ -709,6 +736,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt sendBroadcast(intent); setResult(RESULT_OK, intent); } +// 更新小部件的方法,根据小部件的类型选择不同的小部件提供者,并发送广播更新小部件。 private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener() { public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { @@ -720,6 +748,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt } } }; +// 长按文件夹时创建上下文菜单的监听器,菜单包括查看文件夹、删除文件夹和修改文件夹名称等选项。 @Override public void onContextMenuClosed(Menu menu) { @@ -728,6 +757,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt } super.onContextMenuClosed(menu); } +// 上下文菜单关闭时的操作,将监听器设为null。 @Override public boolean onContextItemSelected(MenuItem item) { @@ -762,6 +792,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt return true; } +// 选择上下文菜单选项时的操作,根据所选选项执行不同的操作,如打开文件夹、删除文件夹或修改文件夹名称。 @Override public boolean onPrepareOptionsMenu(Menu menu) { @@ -780,6 +811,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt } return true; } +// 准备选项菜单时的操作,根据当前的状态显示不同的菜单选项,如笔记列表、子文件夹或通话记录文件夹。 @Override public boolean onOptionsItemSelected(MenuItem item) { @@ -820,6 +852,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt } return true; } +// 选择选项菜单选项时的操作,根据所选选项执行不同的操作,如打开笔记列表、打开子文件夹或打开通话记录文件夹。 @Override public boolean onSearchRequested() { @@ -872,12 +905,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,6 +954,7 @@ 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 + "<>?"; @@ -937,6 +973,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt }, NoteColumns.MODIFIED_DATE + " DESC"); } +// 启动后台查询,以获取目标文件夹列表。它构建一个查询选择器,通过调用 mBackgroundQueryHandler.startQuery() 方法执行查询操作。查询的结果将被传递到 FoldersListAdapter 中进行处理。 public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { if (view instanceof NotesListItem) { @@ -954,4 +991,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; } - } + }//当用户选择同步帐户时调用。在此方法中,更新同步按钮的文本视图,并启用同步按钮。 } From c7a7013c76a187b735c778eb2fecf591638aa311 Mon Sep 17 00:00:00 2001 From: gexinghai <2874903098@qq.com> Date: Tue, 25 Apr 2023 22:49:31 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../buildOutputCleanup.lock | Bin 17 -> 17 bytes .../buildOutputCleanup/cache.properties | 4 ++-- .../buildOutputCleanup/outputFiles.bin | Bin 21143 -> 21251 bytes src/Notes/.gradle/file-system.probe | Bin 8 -> 8 bytes src/Notes/app/build.gradle | 1 + src/Notes/app/src/main/AndroidManifest.xml | 1 - .../net/micode/notes/ui/NoteEditActivity.java | 4 ++-- src/Notes/build.gradle | 2 +- src/Notes/gradle.properties | 3 +++ .../gradle/wrapper/gradle-wrapper.properties | 2 +- 10 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 src/Notes/gradle.properties diff --git a/src/Notes/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/src/Notes/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 954fdfe768077d02bbc42cc917898e521aad2ca1..927f3d8a84bfade90e1cdd9e4c8f429ec154ad09 100644 GIT binary patch literal 17 VcmZRcBz45$;=iS#3}C>t6aY7{1tb6f literal 17 VcmZRcBz45$;=iS#3}C?c0RT7o1#SQU 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 1d2c5943108ac22b6a3999f9d0ad9c43bc29e48c..5e353d5402f6ac4f3c0a512adc9cb5afa6161d80 100644 GIT binary patch literal 21251 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 M%Dhd_|6*VN0Czat1ONa4 literal 21143 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 diff --git a/src/Notes/.gradle/file-system.probe b/src/Notes/.gradle/file-system.probe index efea4229efb376ab89875ee2c5f669481776bd07..9cc85cefe894f155380edfff9b93f4f3aeb377e1 100644 GIT binary patch literal 8 PcmZQzU~FGIW&cC~2`~d1 literal 8 PcmZQzU~FGhz_beh2S)-| 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..a30799f 100644 --- a/src/Notes/app/src/main/AndroidManifest.xml +++ b/src/Notes/app/src/main/AndroidManifest.xml @@ -17,7 +17,6 @@ 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..9cfb996 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 @@ -322,7 +322,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 @@ -387,7 +387,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, }; 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} 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 From 4d914865f17e8ed070cca6c424cfeeaad3f65a00 Mon Sep 17 00:00:00 2001 From: gexinghai <2874903098@qq.com> Date: Thu, 27 Apr 2023 14:42:56 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E6=96=B0=E5=A2=9E=203x3=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=B0=8F=E9=83=A8=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Notes/app/src/main/AndroidManifest.xml | 67 ++++++++++++------- .../net/micode/notes/tool/ResourceParser.java | 14 ++++ .../net/micode/notes/ui/NoteEditActivity.java | 48 +++++++------ .../micode/notes/ui/NotesListActivity.java | 65 ++++++++++-------- .../notes/widget/NoteWidgetProvider_3x.java | 2 +- .../src/main/res/values-zh-rCN/strings.xml | 1 + .../src/main/res/values-zh-rTW/strings.xml | 1 + src/Notes/app/src/main/res/values/strings.xml | 1 + .../app/src/main/res/xml/widget_3x_info.xml | 9 +++ 9 files changed, 133 insertions(+), 75 deletions(-) create mode 100644 src/Notes/app/src/main/res/xml/widget_3x_info.xml diff --git a/src/Notes/app/src/main/AndroidManifest.xml b/src/Notes/app/src/main/AndroidManifest.xml index a30799f..96920fb 100644 --- a/src/Notes/app/src/main/AndroidManifest.xml +++ b/src/Notes/app/src/main/AndroidManifest.xml @@ -18,9 +18,10 @@ + android:versionName="0.1"> - @@ -36,19 +37,19 @@ + android:label="@string/app_name"> - - + + + android:windowSoftInputMode="adjustPan"> @@ -59,14 +60,16 @@ + android:theme="@style/NoteTheme"> - + @@ -74,6 +77,7 @@ + @@ -92,14 +96,14 @@ + android:exported="false" + android:multiprocess="true" /> + android:exported="true" + android:label="@string/app_widget2x2"> @@ -111,11 +115,27 @@ android:resource="@xml/widget_2x_info" /> + + + + + + + + + + + + android:exported="true" + android:label="@string/app_widget4x4"> @@ -129,7 +149,8 @@ - @@ -138,26 +159,22 @@ - + android:process=":remote"> - + android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar"> - + android:theme="@android:style/Theme.Holo.Light"> - + android:exported="false"> 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); @@ -105,6 +108,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, // 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); @@ -113,6 +117,7 @@ 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); @@ -224,7 +229,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, 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())) { + } 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, @@ -328,7 +333,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, // 如果mWorkingNote没有闹钟提醒,则将标题栏中的提醒日期文本和提醒图标设置为不可见。 mNoteHeaderHolder.tvAlertDate.setVisibility(View.GONE); mNoteHeaderHolder.ivAlertIcon.setVisibility(View.GONE); - }; + } + ; } @Override @@ -373,7 +379,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, 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]; @@ -382,8 +388,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, || ev.getX() > (x + view.getWidth()) || ev.getY() < y || ev.getY() > (y + view.getHeight())) { - return false; - } + return false; + } return true; } @@ -407,7 +413,8 @@ 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); /* @@ -415,7 +422,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, * 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); @@ -424,7 +431,7 @@ 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(); @@ -434,15 +441,17 @@ public class NoteEditActivity extends Activity implements OnClickListener, 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_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, "Unspported widget type"); + 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); @@ -450,13 +459,12 @@ public class NoteEditActivity extends Activity implements OnClickListener, }//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); @@ -480,7 +488,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, @Override public void onBackPressed() { - if(clearSettingState()) { + if (clearSettingState()) { return; } @@ -583,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(); @@ -653,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); @@ -687,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 { @@ -705,7 +713,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, /** * 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"); } @@ -725,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++; } @@ -793,7 +801,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, 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); 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 4d980ad..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 @@ -70,6 +70,7 @@ import net.micode.notes.tool.DataUtils; import net.micode.notes.tool.ResourceParser; import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute; import net.micode.notes.widget.NoteWidgetProvider_2x; +import net.micode.notes.widget.NoteWidgetProvider_3x; import net.micode.notes.widget.NoteWidgetProvider_4x; import java.io.BufferedReader; @@ -81,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; @@ -93,7 +94,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt private enum ListEditState { NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER - }; + } + + ; private ListEditState mState; @@ -133,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) { @@ -165,11 +168,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt 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); @@ -182,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) { @@ -261,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(); @@ -311,7 +314,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt }//结束操作模式。该方法结束操作模式。 public void onItemCheckedStateChanged(ActionMode mode, int position, long id, - boolean checked) { + boolean checked) { mNotesListAdapter.setCheckedItem(position, checked); updateMenu(); }//当用户选中或取消选中一个列表项时调用。该方法更新适配器中对应列表项的选中状态,并调用updateMenu()方法更新下拉菜单中的选项。 @@ -329,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; @@ -411,25 +414,27 @@ 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 + // 后台查询处理程序,继承自AsyncQueryHandler private final class BackgroundQueryHandler extends AsyncQueryHandler { public BackgroundQueryHandler(ContentResolver contentResolver) { super(contentResolver); } // 构造函数,调用父类AsyncQueryHandler的构造函数 - // 查询完成后的回调函数,根据token值进行不同的处理 + // 查询完成后的回调函数,根据token值进行不同的处理 @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { switch (token) { @@ -634,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); @@ -652,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)) { @@ -722,15 +727,17 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt 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_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); @@ -958,15 +965,15 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt 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) 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 @@ + + + + +