From f154c9b7705116d13a5be1e09b8bc2f54e764b12 Mon Sep 17 00:00:00 2001 From: zhangjinhan <2403497099@qq.com> Date: Sun, 29 Dec 2024 22:21:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=88=91=E5=B0=86=E6=88=91=E4=B9=8B=E5=89=8D?= =?UTF-8?q?=E6=89=80=E5=A4=84=E7=90=86=E7=9A=84=E9=83=A8=E5=88=86=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E5=88=B0main=E9=87=8C=E9=9D=A2=E6=9D=A5=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/net/micode/notes/model/Note.java | 19 +- .../net/micode/notes/model/WorkingNote.java | 167 ++- .../net/micode/notes/tool/BackupUtils.java | 250 ++-- .../src/net/micode/notes/tool/DataUtils.java | 131 +- .../micode/notes/tool/GTaskStringUtils.java | 146 +- .../net/micode/notes/tool/ResourceParser.java | 235 ++-- .../micode/notes/ui/AlarmAlertActivity.java | 125 +- .../micode/notes/ui/AlarmInitReceiver.java | 23 +- .../net/micode/notes/ui/AlarmReceiver.java | 13 +- .../net/micode/notes/ui/DateTimePicker.java | 1230 ++++++++++------- .../micode/notes/ui/DateTimePickerDialog.java | 37 +- .../src/net/micode/notes/ui/DropdownMenu.java | 29 +- .../micode/notes/ui/FoldersListAdapter.java | 13 +- .../net/micode/notes/ui/NoteEditActivity.java | 282 ++-- .../src/net/micode/notes/ui/NoteEditText.java | 66 +- .../src/net/micode/notes/ui/NoteItemData.java | 99 +- .../micode/notes/ui/NotesListActivity.java | 6 +- .../net/micode/notes/ui/NotesListAdapter.java | 64 +- .../net/micode/notes/ui/NotesListItem.java | 30 +- .../notes/ui/NotesPreferenceActivity.java | 146 +- .../notes/widget/NoteWidgetProvider.java | 45 +- .../notes/widget/NoteWidgetProvider_2x.java | 22 +- .../notes/widget/NoteWidgetProvider_4x.java | 24 +- 23 files changed, 1774 insertions(+), 1428 deletions(-) diff --git a/src/Notes-master/src/net/micode/notes/model/Note.java b/src/Notes-master/src/net/micode/notes/model/Note.java index 6706cf6..6ca854c 100644 --- a/src/Notes-master/src/net/micode/notes/model/Note.java +++ b/src/Notes-master/src/net/micode/notes/model/Note.java @@ -33,7 +33,7 @@ import net.micode.notes.data.Notes.TextNote; import java.util.ArrayList; - +// 代表一个笔记,包含笔记的基本信息和笔记数据 public class Note { private ContentValues mNoteDiffValues; private NoteData mNoteData; @@ -70,36 +70,44 @@ public class Note { mNoteData = new NoteData(); } + // 设置笔记的基本信息 public void setNoteValue(String key, String value) { mNoteDiffValues.put(key, value); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } + // 设置文本笔记的数据 public void setTextData(String key, String value) { mNoteData.setTextData(key, value); } + // 设置文本笔记的数据ID public void setTextDataId(long id) { mNoteData.setTextDataId(id); } + // 获取文本笔记的数据ID public long getTextDataId() { return mNoteData.mTextDataId; } + // 设置通话笔记的数据ID public void setCallDataId(long id) { mNoteData.setCallDataId(id); } + // 设置通话笔记的数据 public void setCallData(String key, String value) { mNoteData.setCallData(key, value); } + // 判断笔记是否被本地修改过 public boolean isLocalModified() { return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); } + // 同步笔记到数据库 public boolean syncNote(Context context, long noteId) { if (noteId <= 0) { throw new IllegalArgumentException("Wrong note id:" + noteId); @@ -130,6 +138,7 @@ public class Note { return true; } + // 笔记数据类,包含文本数据和通话数据 private class NoteData { private long mTextDataId; @@ -148,10 +157,12 @@ public class Note { mCallDataId = 0; } + // 判断笔记数据是否被本地修改过 boolean isLocalModified() { return mTextDataValues.size() > 0 || mCallDataValues.size() > 0; } + // 设置文本数据ID void setTextDataId(long id) { if(id <= 0) { throw new IllegalArgumentException("Text data id should larger than 0"); @@ -159,6 +170,7 @@ public class Note { mTextDataId = id; } + // 设置通话数据ID void setCallDataId(long id) { if (id <= 0) { throw new IllegalArgumentException("Call data id should larger than 0"); @@ -166,18 +178,21 @@ public class Note { mCallDataId = id; } + // 设置通话数据 void setCallData(String key, String value) { mCallDataValues.put(key, value); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } + // 设置文本数据 void setTextData(String key, String value) { mTextDataValues.put(key, value); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } + // 将笔记数据推送到内容解析器 Uri pushIntoContentResolver(Context context, long noteId) { /** * Check for safety @@ -250,4 +265,4 @@ public class Note { return null; } } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/model/WorkingNote.java b/src/Notes-master/src/net/micode/notes/model/WorkingNote.java index be081e4..f77e6e6 100644 --- a/src/Notes-master/src/net/micode/notes/model/WorkingNote.java +++ b/src/Notes-master/src/net/micode/notes/model/WorkingNote.java @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.model; - + import android.appwidget.AppWidgetManager; import android.content.ContentUris; import android.content.Context; import android.database.Cursor; import android.text.TextUtils; import android.util.Log; - + import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.CallNote; import net.micode.notes.data.Notes.DataColumns; @@ -30,8 +30,8 @@ import net.micode.notes.data.Notes.DataConstants; import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.TextNote; import net.micode.notes.tool.ResourceParser.NoteBgResources; - - + +// 表示正在编辑的笔记类 public class WorkingNote { // Note for the working note private Note mNote; @@ -41,27 +41,28 @@ public class WorkingNote { private String mContent; // Note mode private int mMode; - + private long mAlertDate; - + private long mModifiedDate; - + private int mBgColorId; - + private int mWidgetId; - + private int mWidgetType; - + private long mFolderId; - + private Context mContext; - + private static final String TAG = "WorkingNote"; - + private boolean mIsDeleted; - + private NoteSettingChangedListener mNoteSettingStatusListener; - + + // 数据库查询笔记数据的列 public static final String[] DATA_PROJECTION = new String[] { DataColumns.ID, DataColumns.CONTENT, @@ -71,7 +72,8 @@ public class WorkingNote { DataColumns.DATA3, DataColumns.DATA4, }; - + + // 数据库查询笔记信息的列 public static final String[] NOTE_PROJECTION = new String[] { NoteColumns.PARENT_ID, NoteColumns.ALERTED_DATE, @@ -80,28 +82,28 @@ public class WorkingNote { NoteColumns.WIDGET_TYPE, NoteColumns.MODIFIED_DATE }; - + private static final int DATA_ID_COLUMN = 0; - + private static final int DATA_CONTENT_COLUMN = 1; - + private static final int DATA_MIME_TYPE_COLUMN = 2; - + private static final int DATA_MODE_COLUMN = 3; - + private static final int NOTE_PARENT_ID_COLUMN = 0; - + private static final int NOTE_ALERTED_DATE_COLUMN = 1; - + private static final int NOTE_BG_COLOR_ID_COLUMN = 2; - + private static final int NOTE_WIDGET_ID_COLUMN = 3; - + private static final int NOTE_WIDGET_TYPE_COLUMN = 4; - + private static final int NOTE_MODIFIED_DATE_COLUMN = 5; - - // New note construct + + // 新笔记构造方法 private WorkingNote(Context context, long folderId) { mContext = context; mAlertDate = 0; @@ -113,8 +115,8 @@ public class WorkingNote { mMode = 0; mWidgetType = Notes.TYPE_WIDGET_INVALIDE; } - - // Existing note construct + + // 已有笔记构造方法 private WorkingNote(Context context, long noteId, long folderId) { mContext = context; mNoteId = noteId; @@ -123,12 +125,13 @@ public class WorkingNote { mNote = new Note(); loadNote(); } - + + // 从数据库加载笔记信息 private void loadNote() { Cursor cursor = mContext.getContentResolver().query( ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null, null, null); - + if (cursor != null) { if (cursor.moveToFirst()) { mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN); @@ -145,13 +148,14 @@ public class WorkingNote { } loadNoteData(); } - + + // 从数据库加载笔记数据 private void loadNoteData() { Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] { String.valueOf(mNoteId) }, null); - + if (cursor != null) { if (cursor.moveToFirst()) { do { @@ -173,7 +177,8 @@ public class WorkingNote { throw new IllegalArgumentException("Unable to find note's data with id " + mNoteId); } } - + + // 创建一个空笔记 public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId, int widgetType, int defaultBgColorId) { WorkingNote note = new WorkingNote(context, folderId); @@ -182,11 +187,13 @@ public class WorkingNote { note.setWidgetType(widgetType); return note; } - + + // 从数据库加载笔记 public static WorkingNote load(Context context, long id) { return new WorkingNote(context, id, 0); } - + + // 保存笔记到数据库 public synchronized boolean saveNote() { if (isWorthSaving()) { if (!existInDatabase()) { @@ -195,9 +202,9 @@ public class WorkingNote { return false; } } - + mNote.syncNote(mContext, mNoteId); - + /** * Update widget content if there exist any widget of this note */ @@ -211,11 +218,13 @@ public class WorkingNote { return false; } } - + + // 判断笔记是否存在于数据库中 public boolean existInDatabase() { return mNoteId > 0; } - + + // 判断笔记是否值得保存 private boolean isWorthSaving() { if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent)) || (existInDatabase() && !mNote.isLocalModified())) { @@ -224,11 +233,13 @@ public class WorkingNote { return true; } } - + + // 设置笔记信息改变监听器 public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) { mNoteSettingStatusListener = l; } - + + // 设置闹钟提醒日期 public void setAlertDate(long date, boolean set) { if (date != mAlertDate) { mAlertDate = date; @@ -238,7 +249,8 @@ public class WorkingNote { mNoteSettingStatusListener.onClockAlertChanged(date, set); } } - + + // 标记笔记是否已删除 public void markDeleted(boolean mark) { mIsDeleted = mark; if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID @@ -246,7 +258,8 @@ public class WorkingNote { mNoteSettingStatusListener.onWidgetChanged(); } } - + + // 设置笔记背景颜色ID public void setBgColorId(int id) { if (id != mBgColorId) { mBgColorId = id; @@ -256,7 +269,8 @@ public class WorkingNote { mNote.setNoteValue(NoteColumns.BG_COLOR_ID, String.valueOf(id)); } } - + + // 设置笔记的检查列表模式 public void setCheckListMode(int mode) { if (mMode != mode) { if (mNoteSettingStatusListener != null) { @@ -266,98 +280,115 @@ public class WorkingNote { mNote.setTextData(TextNote.MODE, String.valueOf(mMode)); } } - + + // 设置笔记的窗口小部件类型 public void setWidgetType(int type) { if (type != mWidgetType) { mWidgetType = type; mNote.setNoteValue(NoteColumns.WIDGET_TYPE, String.valueOf(mWidgetType)); } } - + + // 设置笔记的窗口小部件ID public void setWidgetId(int id) { if (id != mWidgetId) { mWidgetId = id; mNote.setNoteValue(NoteColumns.WIDGET_ID, String.valueOf(mWidgetId)); } } - + + // 设置工作文本内容 public void setWorkingText(String text) { if (!TextUtils.equals(mContent, text)) { mContent = text; mNote.setTextData(DataColumns.CONTENT, mContent); } } - + + // 将笔记转换为通话笔记 public void convertToCallNote(String phoneNumber, long callDate) { mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate)); mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber); mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER)); } - + + // 检查笔记是否有闹钟提醒 public boolean hasClockAlert() { return (mAlertDate > 0 ? true : false); } - + + // 获取笔记内容 public String getContent() { return mContent; } - + + // 获取闹钟提醒日期 public long getAlertDate() { return mAlertDate; } - + + // 获取笔记修改日期 public long getModifiedDate() { return mModifiedDate; } - + + // 获取笔记背景颜色资源ID public int getBgColorResId() { return NoteBgResources.getNoteBgResource(mBgColorId); } - + + // 获取笔记背景颜色ID public int getBgColorId() { return mBgColorId; } - + + // 获取笔记标题背景颜色资源ID public int getTitleBgResId() { return NoteBgResources.getNoteTitleBgResource(mBgColorId); } - + + // 获取检查列表模式 public int getCheckListMode() { return mMode; } - + + // 获取笔记ID public long getNoteId() { return mNoteId; } - + + // 获取笔记所在的文件夹ID public long getFolderId() { return mFolderId; } - + + // 获取窗口小部件ID public int getWidgetId() { return mWidgetId; } - + + // 获取窗口小部件类型 public int getWidgetType() { return mWidgetType; } - + + // 笔记信息改变监听器接口 public interface NoteSettingChangedListener { /** * Called when the background color of current note has just changed */ void onBackgroundColorChanged(); - + /** * Called when user set clock */ void onClockAlertChanged(long date, boolean set); - + /** * Call when user create note from widget */ void onWidgetChanged(); - + /** * Call when switch between check list mode and normal mode * @param oldMode is previous mode before change @@ -365,4 +396,4 @@ public class WorkingNote { */ void onCheckListModeChanged(int oldMode, int newMode); } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/tool/BackupUtils.java b/src/Notes-master/src/net/micode/notes/tool/BackupUtils.java index ffae194..c6a1095 100644 --- a/src/Notes-master/src/net/micode/notes/tool/BackupUtils.java +++ b/src/Notes-master/src/net/micode/notes/tool/BackupUtils.java @@ -1,112 +1,110 @@ -以下是带有中文注释的代码: - -```java /* * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * - * 根据Apache License, Version 2.0(以下简称“许可证”)授权; - * 除非遵守许可证,否则不得使用此文件。 - * 你可以在以下网址获得许可证的副本: + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * 除非适用法律要求或书面同意,否则按“原样”提供软件 - * 在许可证下分发,不附带任何明示或暗示的保证或条件。 - * 请参阅许可证,了解有关权限和限制的具体语言。 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - + package net.micode.notes.tool; - + import android.content.Context; import android.database.Cursor; import android.os.Environment; import android.text.TextUtils; import android.text.format.DateFormat; import android.util.Log; - + import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.DataColumns; import net.micode.notes.data.Notes.DataConstants; import net.micode.notes.data.Notes.NoteColumns; - + import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; - -// 备份工具类,用于将笔记数据备份到文本文件中。 + +// 备份工具类,用于将笔记数据导出为文本文件 public class BackupUtils { private static final String TAG = "BackupUtils"; - // 单例模式 + // 单例实例 private static BackupUtils sInstance; - - // 获取BackupUtils的单例,如果不存在则创建。 + + // 获取BackupUtils的单例实例 public static synchronized BackupUtils getInstance(Context context) { if (sInstance == null) { sInstance = new BackupUtils(context); } return sInstance; } - + /** - * 以下状态码用于表示备份或恢复的状态。 + * 以下状态码表示备份或恢复的状态 */ // SD卡未挂载 - public static final int STATE_SD_CARD_UNMOUONTED = 0; + public static final int STATE_SD_CARD_UNMOUONTED = 0; // 备份文件不存在 - public static final int STATE_BACKUP_FILE_NOT_EXIST = 1; - // 数据格式不正确,可能被其他程序更改 - public static final int STATE_DATA_DESTROIED = 2; - // 运行时异常导致备份或恢复失败 - public static final int STATE_SYSTEM_ERROR = 3; + public static final int STATE_BACKUP_FILE_NOT_EXIST = 1; + // 数据损坏或格式不正确 + public static final int STATE_DATA_DESTROIED = 2; + // 系统错误导致备份或恢复失败 + public static final int STATE_SYSTEM_ERROR = 3; // 备份或恢复成功 - public static final int STATE_SUCCESS = 4; - + public static final int STATE_SUCCESS = 4; + private TextExport mTextExport; - - // 私有构造函数,用于创建BackupUtils实例。 + + // 构造函数,初始化TextExport实例 private BackupUtils(Context context) { mTextExport = new TextExport(context); } - - // 检查外部存储是否可用。 + + // 检查外部存储是否可用 private static boolean externalStorageAvailable() { return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); } - - // 导出笔记数据到文本文件。 + + // 导出笔记数据为文本文件 public int exportToText() { return mTextExport.exportToText(); } - - // 获取导出的文本文件名。 + + // 获取导出的文本文件名 public String getExportedTextFileName() { return mTextExport.mFileName; } - - // 获取导出的文本文件目录。 + + // 获取导出的文本文件目录 public String getExportedTextFileDir() { return mTextExport.mFileDirectory; } - - // 内部类,用于将笔记数据导出到文本。 + + // 文本导出类,用于将笔记数据导出为文本格式 private static class TextExport { - // 笔记数据投影数组。 private static final String[] NOTE_PROJECTION = { NoteColumns.ID, NoteColumns.MODIFIED_DATE, NoteColumns.SNIPPET, NoteColumns.TYPE }; - - // 数据列索引。 + private static final int NOTE_COLUMN_ID = 0; + private static final int NOTE_COLUMN_MODIFIED_DATE = 1; + private static final int NOTE_COLUMN_SNIPPET = 2; - - // 数据数据投影数组。 + private static final String[] DATA_PROJECTION = { DataColumns.CONTENT, DataColumns.MIME_TYPE, @@ -115,56 +113,53 @@ public class BackupUtils { DataColumns.DATA3, DataColumns.DATA4, }; - - // 数据列索引。 + private static final int DATA_COLUMN_CONTENT = 0; + private static final int DATA_COLUMN_MIME_TYPE = 1; + private static final int DATA_COLUMN_CALL_DATE = 2; + private static final int DATA_COLUMN_PHONE_NUMBER = 4; - - // 导出文本的格式数组。 - private final String[] TEXT_FORMAT; - private static final int FORMAT_FOLDER_NAME = 0; - private static final int FORMAT_NOTE_DATE = 1; - private static final int FORMAT_NOTE_CONTENT = 2; - - // 上下文对象,用于访问资源和内容解析器。 + + private final String [] TEXT_FORMAT; + private static final int FORMAT_FOLDER_NAME = 0; + private static final int FORMAT_NOTE_DATE = 1; + private static final int FORMAT_NOTE_CONTENT = 2; + private Context mContext; - // 导出文件的名称和目录。 private String mFileName; private String mFileDirectory; - - // 构造函数,初始化上下文和格式数组。 + + // 构造函数,初始化导出格式和上下文 public TextExport(Context context) { TEXT_FORMAT = context.getResources().getStringArray(R.array.format_for_exported_note); mContext = context; mFileName = ""; mFileDirectory = ""; } - - // 根据ID获取对应的格式字符串。 + + // 根据ID获取导出格式字符串 private String getFormat(int id) { return TEXT_FORMAT[id]; } - - /** - * 将指定文件夹ID的笔记导出到文本。 - */ + + // 导出指定文件夹下的笔记到文本文件 private void exportFolderToText(String folderId, PrintStream ps) { - // 查询属于该文件夹的笔记。 + // 查询属于该文件夹的笔记 Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI, NOTE_PROJECTION, NoteColumns.PARENT_ID + "=?", new String[] { - folderId + folderId }, null); - + if (notesCursor != null) { if (notesCursor.moveToFirst()) { do { - // 打印笔记最后修改日期。 + // 打印笔记的最后修改日期 ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( mContext.getString(R.string.format_datetime_mdhm), notesCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); - // 查询属于该笔记的数据。 + // 查询属于该笔记的数据 String noteId = notesCursor.getString(NOTE_COLUMN_ID); exportNoteToText(noteId, ps); } while (notesCursor.moveToNext()); @@ -172,16 +167,14 @@ public class BackupUtils { notesCursor.close(); } } - - /** - * 将指定ID的笔记导出到打印流。 - */ + + // 导出指定笔记到文本输出流 private void exportNoteToText(String noteId, PrintStream ps) { Cursor dataCursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] { - noteId + noteId }, null); - + if (dataCursor != null) { if (dataCursor.moveToFirst()) { do { @@ -191,7 +184,7 @@ public class BackupUtils { String phoneNumber = dataCursor.getString(DATA_COLUMN_PHONE_NUMBER); long callDate = dataCursor.getLong(DATA_COLUMN_CALL_DATE); String location = dataCursor.getString(DATA_COLUMN_CONTENT); - + if (!TextUtils.isEmpty(phoneNumber)) { ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), phoneNumber)); @@ -216,7 +209,7 @@ public class BackupUtils { } dataCursor.close(); } - // 打印笔记之间的分隔线。 + // 打印笔记之间的分隔符 try { ps.write(new byte[] { Character.LINE_SEPARATOR, Character.LETTER_NUMBER @@ -225,36 +218,33 @@ public class BackupUtils { Log.e(TAG, e.toString()); } } - - /** - * 将笔记导出为用户可读的文本。 - */ + + // 将笔记数据导出为用户可读的文本文件 public int exportToText() { if (!externalStorageAvailable()) { - Log.d(TAG, "媒体未挂载"); + Log.d(TAG, "Media was not mounted"); return STATE_SD_CARD_UNMOUONTED; } - + PrintStream ps = getExportToTextPrintStream(); if (ps == null) { - Log.e(TAG, "获取打印流出错"); + Log.e(TAG, "get print stream error"); return STATE_SYSTEM_ERROR; } - // 首先导出文件夹及其笔记。 + // 首先导出文件夹及其笔记 Cursor folderCursor = mContext.getContentResolver().query( Notes.CONTENT_NOTE_URI, NOTE_PROJECTION, "(" + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + ") OR " - + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER, - null, null); - + + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER, null, null); + if (folderCursor != null) { if (folderCursor.moveToFirst()) { do { // 打印文件夹名称 String folderName = ""; - if (folderCursor.getLong(NOTE_COLUMN_ID) == Notes.ID_CALL_RECORD_FOLDER) { + if(folderCursor.getLong(NOTE_COLUMN_ID) == Notes.ID_CALL_RECORD_FOLDER) { folderName = mContext.getString(R.string.call_record_folder_name); } else { folderName = folderCursor.getString(NOTE_COLUMN_SNIPPET); @@ -268,22 +258,21 @@ public class BackupUtils { } folderCursor.close(); } - - // 导出根文件夹中的笔记。 - // 导出根文件夹中的笔记 + + // 导出根文件夹下的笔记 Cursor noteCursor = mContext.getContentResolver().query( Notes.CONTENT_NOTE_URI, NOTE_PROJECTION, - NoteColumns.TYPE + "=" + Notes.TYPE_NOTE + " AND " + NoteColumns.PARENT_ID + "=0", null, null); - + NoteColumns.TYPE + "=" + +Notes.TYPE_NOTE + " AND " + NoteColumns.PARENT_ID + + "=0", null, null); + if (noteCursor != null) { if (noteCursor.moveToFirst()) { do { - // 打印笔记最后修改日期 ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( mContext.getString(R.string.format_datetime_mdhm), noteCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); - // 查询属于这条笔记的数据 + // 查询属于该笔记的数据 String noteId = noteCursor.getString(NOTE_COLUMN_ID); exportNoteToText(noteId, ps); } while (noteCursor.moveToNext()); @@ -291,20 +280,16 @@ public class BackupUtils { noteCursor.close(); } ps.close(); - - // 返回成功状态码 + return STATE_SUCCESS; } - - /** - * 获取指向导出文本文件的打印流 - */ + + // 获取指向导出文本文件的PrintStream private PrintStream getExportToTextPrintStream() { - // 生成存储导出数据的文本文件 File file = generateFileMountedOnSDcard(mContext, R.string.file_path, R.string.file_name_txt_format); if (file == null) { - Log.e(TAG, "创建导出文件失败"); + Log.e(TAG, "create file to exported failed"); return null; } mFileName = file.getName(); @@ -323,34 +308,33 @@ public class BackupUtils { return ps; } } - -/** - * 在SD卡上生成用于存储导入数据的文本文件 - */ -private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) { - StringBuilder sb = new StringBuilder(); - sb.append(Environment.getExternalStorageDirectory()); - sb.append(context.getString(filePathResId)); - File filedir = new File(sb.toString()); - sb.append(context.getString( - fileNameFormatResId, - DateFormat.format(context.getString(R.string.format_date_ymd), - System.currentTimeMillis()))); - File file = new File(sb.toString()); - - try { - if (!filedir.exists()) { - filedir.mkdir(); - } - if (!file.exists()) { - file.createNewFile(); + + // 生成用于存储导入数据的文本文件 + private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) { + StringBuilder sb = new StringBuilder(); + sb.append(Environment.getExternalStorageDirectory()); + sb.append(context.getString(filePathResId)); + File filedir = new File(sb.toString()); + sb.append(context.getString( + fileNameFormatResId, + DateFormat.format(context.getString(R.string.format_date_ymd), + System.currentTimeMillis()))); + File file = new File(sb.toString()); + + try { + if (!filedir.exists()) { + filedir.mkdir(); + } + if (!file.exists()) { + file.createNewFile(); + } + return file; + } catch (SecurityException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); } - return file; - } catch (SecurityException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); + + return null; } - - return null; -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/tool/DataUtils.java b/src/Notes-master/src/net/micode/notes/tool/DataUtils.java index d0c852a..7de4569 100644 --- a/src/Notes-master/src/net/micode/notes/tool/DataUtils.java +++ b/src/Notes-master/src/net/micode/notes/tool/DataUtils.java @@ -1,16 +1,17 @@ - /* * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * - * 根据Apache License, Version 2.0(以下简称“许可证”)授权; - * 除非遵守许可证,否则不得使用此文件。 - * 你可以在以下网址获得许可证的副本: + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * 除非适用法律要求或书面同意,否则按“原样”提供软件 - * 在许可证下分发,不附带任何明示或暗示的保证或条件。 - * 请参阅许可证,了解有关权限和限制的具体语言。 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package net.micode.notes.tool; @@ -33,25 +34,25 @@ import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute; import java.util.ArrayList; import java.util.HashSet; -// 数据工具类,提供对笔记数据的操作函数 +// 数据工具类,提供批量删除笔记、移动笔记到文件夹等操作 public class DataUtils { public static final String TAG = "DataUtils"; // 批量删除笔记 public static boolean batchDeleteNotes(ContentResolver resolver, HashSet ids) { if (ids == null) { - Log.d(TAG, "id集合为空"); + Log.d(TAG, "the ids is null"); return true; } if (ids.size() == 0) { - Log.d(TAG, "id集合中没有元素"); + Log.d(TAG, "no id is in the hashset"); return true; } ArrayList operationList = new ArrayList(); for (long id : ids) { - if (id == Notes.ID_ROOT_FOLDER) { - Log.e(TAG, "不要删除系统根文件夹"); + if(id == Notes.ID_ROOT_FOLDER) { + Log.e(TAG, "Don't delete system folder root"); continue; } ContentProviderOperation.Builder builder = ContentProviderOperation @@ -61,7 +62,7 @@ public class DataUtils { try { ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); if (results == null || results.length == 0 || results[0] == null) { - Log.d(TAG, "删除笔记失败, ids:" + ids.toString()); + Log.d(TAG, "delete notes failed, ids:" + ids.toString()); return false; } return true; @@ -86,7 +87,7 @@ public class DataUtils { public static boolean batchMoveToFolder(ContentResolver resolver, HashSet ids, long folderId) { if (ids == null) { - Log.d(TAG, "id集合为空"); + Log.d(TAG, "the ids is null"); return true; } @@ -102,7 +103,7 @@ public class DataUtils { try { ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); if (results == null || results.length == 0 || results[0] == null) { - Log.d(TAG, "移动笔记失败, ids:" + ids.toString()); + Log.d(TAG, "delete notes failed, ids:" + ids.toString()); return false; } return true; @@ -115,22 +116,22 @@ public class DataUtils { } /** - * 获取除了系统文件夹外的所有文件夹数量 + * 获取用户文件夹(非系统文件夹)的数量 */ public static int getUserFolderCount(ContentResolver resolver) { - Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, + Cursor cursor =resolver.query(Notes.CONTENT_NOTE_URI, new String[] { "COUNT(*)" }, NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?", - new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER) }, + new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)}, null); int count = 0; - if (cursor != null) { - if (cursor.moveToFirst()) { + if(cursor != null) { + if(cursor.moveToFirst()) { try { count = cursor.getInt(0); } catch (IndexOutOfBoundsException e) { - Log.e(TAG, "获取文件夹数量失败:" + e.toString()); + Log.e(TAG, "get folder count failed:" + e.toString()); } finally { cursor.close(); } @@ -139,12 +140,12 @@ public class DataUtils { return count; } - // 检查笔记在数据库中是否可见 + // 检查指定类型的笔记是否可见 public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) { Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null, NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER, - new String[] { String.valueOf(type) }, + new String [] {String.valueOf(type)}, null); boolean exist = false; @@ -157,7 +158,7 @@ public class DataUtils { return exist; } - // 检查笔记在数据库中是否存在 + // 检查笔记是否存在于数据库中 public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) { Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null, null, null, null); @@ -172,7 +173,7 @@ public class DataUtils { return exist; } - // 检查数据在数据库中是否存在 + // 检查数据是否存在于数据库中 public static boolean existInDataDatabase(ContentResolver resolver, long dataId) { Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null, null, null, null); @@ -187,16 +188,16 @@ public class DataUtils { return exist; } - // 检查文件夹名称是否可见 + // 检查指定名称的用户文件夹是否存在 public static boolean checkVisibleFolderName(ContentResolver resolver, String name) { Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, null, NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + - " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + - " AND " + NoteColumns.SNIPPET + "=?", + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + + " AND " + NoteColumns.SNIPPET + "=?", new String[] { name }, null); boolean exist = false; - if (cursor != null) { - if (cursor.getCount() > 0) { + if(cursor != null) { + if(cursor.getCount() > 0) { exist = true; } cursor.close(); @@ -204,7 +205,7 @@ public class DataUtils { return exist; } - // 获取文件夹笔记的小部件属性 + // 获取指定文件夹下的笔记小部件信息 public static HashSet getFolderNoteWidget(ContentResolver resolver, long folderId) { Cursor c = resolver.query(Notes.CONTENT_NOTE_URI, new String[] { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE }, @@ -234,80 +235,74 @@ public class DataUtils { // 根据笔记ID获取通话号码 public static String getCallNumberByNoteId(ContentResolver resolver, long noteId) { - Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, - new String [] { CallNote.PHONE_NUMBER }, - CallNote.NOTE_ID + "=? AND " + CallNote.MIME_TYPE + "=?", - new String [] { String.valueOf(noteId), CallNote.CONTENT_ITEM_TYPE }, - null); - - - - + Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, + new String [] { CallNote.PHONE_NUMBER }, + CallNote.NOTE_ID + "=? AND " + CallNote.MIME_TYPE + "=?", + new String [] { String.valueOf(noteId), CallNote.CONTENT_ITEM_TYPE }, + null); - // 如果游标不为空并且移动到第一行,则尝试获取通话号码 if (cursor != null && cursor.moveToFirst()) { try { - return cursor.getString(0); // 返回获取到的字符串 + return cursor.getString(0); } catch (IndexOutOfBoundsException e) { - Log.e(TAG, "获取通话号码失败:" + e.toString()); // 记录异常信息 + Log.e(TAG, "Get call number fails " + e.toString()); } finally { - cursor.close(); // 确保游标被关闭 + cursor.close(); } } - return ""; // 如果失败,返回空字符串 + return ""; + } - // 根据电话号码和通话日期获取笔记ID + // 根据通话号码和通话日期获取笔记ID public static long getNoteIdByPhoneNumberAndCallDate(ContentResolver resolver, String phoneNumber, long callDate) { Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, - new String[] { CallNote.NOTE_ID }, + new String [] { CallNote.NOTE_ID }, CallNote.CALL_DATE + "=? AND " + CallNote.MIME_TYPE + "=? AND PHONE_NUMBERS_EQUAL(" - + CallNote.PHONE_NUMBER + ",?)", - new String[] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber }, + + CallNote.PHONE_NUMBER + ",?)", + new String [] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber }, null); - // 如果游标不为空并且移动到第一行,则尝试获取笔记ID if (cursor != null) { if (cursor.moveToFirst()) { try { - return cursor.getLong(0); // 返回获取到的长整型数 + return cursor.getLong(0); } catch (IndexOutOfBoundsException e) { - Log.e(TAG, "获取通话笔记ID失败:" + e.toString()); // 记录异常信息 + Log.e(TAG, "Get call note id fails " + e.toString()); } } - cursor.close(); // 确保游标被关闭 + cursor.close(); } - return 0; // 如果失败,返回0 + return 0; } - // 根据笔记ID获取摘要 + // 根据笔记ID获取笔记摘要 public static String getSnippetById(ContentResolver resolver, long noteId) { Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, - new String[] { NoteColumns.SNIPPET }, + new String [] { NoteColumns.SNIPPET }, NoteColumns.ID + "=?", - new String[] { String.valueOf(noteId) }, + new String [] { String.valueOf(noteId)}, null); - // 如果游标不为空并且移动到第一行,则尝试获取摘要 if (cursor != null) { String snippet = ""; if (cursor.moveToFirst()) { - snippet = cursor.getString(0); // 获取摘要 + snippet = cursor.getString(0); } - cursor.close(); // 确保游标被关闭 - return snippet; // 返回摘要 + cursor.close(); + return snippet; } - throw new IllegalArgumentException("未找到ID为:" + noteId + "的笔记"); // 如果失败,抛出异常 + throw new IllegalArgumentException("Note is not found with id: " + noteId); } - // 获取格式化后的摘要 + // 格式化笔记摘要 public static String getFormattedSnippet(String snippet) { if (snippet != null) { - snippet = snippet.trim(); // 去除首尾空白 - int index = snippet.indexOf('\n'); // 查找换行符 + snippet = snippet.trim(); + int index = snippet.indexOf('\n'); if (index != -1) { - snippet = snippet.substring(0, index); // 截取换行符之前的字符串 + snippet = snippet.substring(0, index); } } - return snippet; // 返回格式化后的摘要 + return snippet; } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/tool/GTaskStringUtils.java b/src/Notes-master/src/net/micode/notes/tool/GTaskStringUtils.java index 1b42c6f..8903dd7 100644 --- a/src/Notes-master/src/net/micode/notes/tool/GTaskStringUtils.java +++ b/src/Notes-master/src/net/micode/notes/tool/GTaskStringUtils.java @@ -13,148 +13,102 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.tool; - -// GTaskStringUtils类,主要用于定义一些与Google Tasks相关操作中使用的字符串常量,方便在代码中统一引用和管理 + +// 此类用于定义和存储GTask相关的JSON字段名常量 public class GTaskStringUtils { - - // 表示操作的唯一ID的JSON键名,用于在与Google Tasks交互的JSON数据中标识某个具体操作的ID + public final static String GTASK_JSON_ACTION_ID = "action_id"; - - // 表示操作列表的JSON键名,用于在与Google Tasks交互的JSON数据中存放一组操作的集合(通常是一个JSON数组) + public final static String GTASK_JSON_ACTION_LIST = "action_list"; - - // 表示操作类型的JSON键名,用于在与Google Tasks交互的JSON数据中指定某个操作具体是什么类型的操作,比如创建、获取、移动等 + public final static String GTASK_JSON_ACTION_TYPE = "action_type"; - - // 表示创建操作类型的具体值,对应创建相关的操作,例如创建任务、创建任务列表等操作时使用该值来标识操作类型 + public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create"; - - // 表示获取所有(任务等)操作类型的具体值,用于获取某个任务列表下的所有任务等情况时标识操作类型 + public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all"; - - // 表示移动操作类型的具体值,用于在移动任务、任务列表等位置时标识操作类型 + public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move"; - - // 表示更新操作类型的具体值,用于对任务、任务列表等进行更新操作时标识操作类型 + public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update"; - - // 表示创建者ID的JSON键名,用于在与Google Tasks交互的JSON数据中存放创建某个任务、任务列表等的用户ID信息 + public final static String GTASK_JSON_CREATOR_ID = "creator_id"; - - // 表示子实体的JSON键名,可能用于在涉及包含子元素的结构(如任务列表包含多个任务等情况)时,标识子实体相关信息 + public final static String GTASK_JSON_CHILD_ENTITY = "child_entity"; - - // 表示客户端版本号的JSON键名,用于在与Google Tasks交互的JSON数据中告知服务器当前客户端的版本信息,便于进行兼容性等相关处理 + public final static String GTASK_JSON_CLIENT_VERSION = "client_version"; - - // 表示是否完成的JSON键名,可能用于任务等实体中,标识该任务是否已经完成的状态信息 + public final static String GTASK_JSON_COMPLETED = "completed"; - - // 表示当前列表ID的JSON键名,可能用于在涉及多列表切换、关联等场景时,标识当前所在的任务列表的ID + public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id"; - - // 表示默认列表ID的JSON键名,用于标识某个用户、某个应用场景下的默认任务列表的ID信息 + public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id"; - - // 表示是否已删除的JSON键名,用于在任务、任务列表等实体中标识其是否已经被删除的状态信息 + public final static String GTASK_JSON_DELETED = "deleted"; - - // 表示目标列表的JSON键名,在进行移动操作等涉及改变所属列表的操作时,用于指定要移动到的目标任务列表的ID + public final static String GTASK_JSON_DEST_LIST = "dest_list"; - - // 表示目标父级的JSON键名,在进行移动操作、关联操作等涉及改变父级元素的情况时,用于指定要移动到或关联的目标父级元素的相关信息(比如任务列表等) + public final static String GTASK_JSON_DEST_PARENT = "dest_parent"; - - // 表示目标父级类型的JSON键名,可能用于进一步明确目标父级元素的具体类型(例如是任务列表类型还是其他类型等) + public final static String GTASK_JSON_DEST_PARENT_TYPE = "dest_parent_type"; - - // 表示实体差异的JSON键名,可能用于在对比、更新实体时,标识实体之间发生变化的部分相关信息 + public final static String GTASK_JSON_ENTITY_DELTA = "entity_delta"; - - // 表示实体类型的JSON键名,用于在与Google Tasks交互的JSON数据中明确某个实体(如任务、任务列表等)具体是什么类型 + public final static String GTASK_JSON_ENTITY_TYPE = "entity_type"; - - // 表示是否获取已删除的JSON键名,在进行查询操作时,用于指定是否要获取已经被标记为删除的任务、任务列表等信息 + public final static String GTASK_JSON_GET_DELETED = "get_deleted"; - - // 表示唯一ID的JSON键名,通常用于标识任务、任务列表等实体在Google Tasks系统中的全局唯一标识符 + public final static String GTASK_JSON_ID = "id"; - - // 表示索引的JSON键名,可能用于在任务列表中标识某个任务的排列顺序等索引相关信息 + public final static String GTASK_JSON_INDEX = "index"; - - // 表示最后修改时间的JSON键名,用于记录任务、任务列表等实体最后一次被修改的时间信息,便于进行同步、更新等操作时的判断 + public final static String GTASK_JSON_LAST_MODIFIED = "last_modified"; - - // 表示最新同步点的JSON键名,可能用于记录与Google Tasks进行数据同步时的最新同步时间点等相关信息,便于后续判断同步范围、增量等情况 + public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point"; - - // 表示列表ID的JSON键名,常用于标识某个具体的任务列表的ID信息,与其他相关操作配合使用,比如获取某个列表下的任务等操作 + public final static String GTASK_JSON_LIST_ID = "list_id"; - - // 表示任务列表(复数形式)的JSON键名,用于在与Google Tasks交互的JSON数据中存放多个任务列表信息的集合(通常是一个JSON数组) + public final static String GTASK_JSON_LISTS = "lists"; - - // 表示名称的JSON键名,用于任务、任务列表等实体中,存放它们的名称信息,方便展示、识别等操作 + public final static String GTASK_JSON_NAME = "name"; - - // 表示新ID的JSON键名,可能在某些创建、更新操作后,用于存放新生成的实体ID信息(比如创建任务后返回的新任务ID等情况) + public final static String GTASK_JSON_NEW_ID = "new_id"; - - // 表示备注(笔记)的JSON键名,可能用于存放与任务相关的一些备注、说明等文本信息 + public final static String GTASK_JSON_NOTES = "notes"; - - // 表示父级ID的JSON键名,用于在任务、任务列表等实体中标识其所属的父级元素的ID信息,建立层级关系 + public final static String GTASK_JSON_PARENT_ID = "parent_id"; - - // 表示前一个兄弟节点(任务等)ID的JSON键名,在任务列表中用于标识某个任务之前相邻的兄弟任务的ID,常用于排序、移动等操作场景 + public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id"; - - // 表示操作结果的JSON键名,在执行某些操作(如批量操作等)后,用于存放操作的结果信息(通常是一个JSON数组) + public final static String GTASK_JSON_RESULTS = "results"; - - // 表示源列表的JSON键名,在进行移动操作等涉及改变所属列表的操作时,用于指定操作前所在的原始任务列表的ID + public final static String GTASK_JSON_SOURCE_LIST = "source_list"; - - // 表示任务(复数形式)的JSON键名,用于在与Google Tasks交互的JSON数据中存放多个任务信息的集合(通常是一个JSON数组) + public final static String GTASK_JSON_TASKS = "tasks"; - - // 表示类型的JSON键名,用于在与Google - // Tasks交互的JSON数据中明确某个实体(如任务、任务列表等)具体是什么类型,和GTASK_JSON_ENTITY_TYPE作用类似但使用场景可能稍有不同 + public final static String GTASK_JSON_TYPE = "type"; - - // 表示分组类型的具体值,用于标识某个实体是分组类型(例如任务分组等情况) + public final static String GTASK_JSON_TYPE_GROUP = "GROUP"; - - // 表示任务类型的具体值,用于明确某个实体是任务类型,方便在代码中进行类型判断等操作 + public final static String GTASK_JSON_TYPE_TASK = "TASK"; - - // 表示用户的JSON键名,可能用于存放与操作相关的用户信息,比如执行操作的用户账号等情况 + public final static String GTASK_JSON_USER = "user"; - - // MIUI系统中笔记相关的文件夹前缀字符串,用于在名称等地方标识该文件夹是属于MIUI笔记应用相关的文件夹 + public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]"; - - // 表示默认文件夹名称的字符串常量,用于标识默认的任务列表、文件夹等的名称 + public final static String FOLDER_DEFAULT = "Default"; - - // 表示通话记录笔记文件夹名称的字符串常量,用于明确该文件夹是存放通话记录相关笔记的 + public final static String FOLDER_CALL_NOTE = "Call_Note"; - - // 表示元数据文件夹名称的字符串常量,用于标识存放元数据相关内容的文件夹名称 + public final static String FOLDER_META = "METADATA"; - - // 表示元数据中Google Tasks ID的键名,可能用于在元数据结构中关联对应的Google Tasks实体的ID信息 + public final static String META_HEAD_GTASK_ID = "meta_gid"; - - // 表示元数据中笔记相关内容的键名,用于在元数据结构中存放与笔记相关的具体信息 + public final static String META_HEAD_NOTE = "meta_note"; - - // 表示元数据中数据相关内容的键名,用于在元数据结构中存放一些额外的数据信息(可能是和任务、笔记等相关的数据集合等情况) + public final static String META_HEAD_DATA = "meta_data"; - - // 表示元数据笔记名称的字符串常量,同时提示不要更新和删除该元数据笔记(可能是具有特殊用途的固定元数据相关说明) + public final static String META_NOTE_NAME = "[META INFO] DON'T UPDATE AND DELETE"; + } \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/tool/ResourceParser.java b/src/Notes-master/src/net/micode/notes/tool/ResourceParser.java index d98a327..b813795 100644 --- a/src/Notes-master/src/net/micode/notes/tool/ResourceParser.java +++ b/src/Notes-master/src/net/micode/notes/tool/ResourceParser.java @@ -13,71 +13,66 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -// 该类所属的包名,表明这个类位于net.micode.notes.tool包下,用于提供一些资源相关的解析和获取功能 + package net.micode.notes.tool; - + import android.content.Context; import android.preference.PreferenceManager; - + import net.micode.notes.R; import net.micode.notes.ui.NotesPreferenceActivity; - -// ResourceParser类,主要用于对应用中的各种资源(如背景图片、文本样式等)进行管理和提供获取方法,方便在不同的界面等场景中使用 + public class ResourceParser { - - // 定义颜色相关的常量,用整数表示不同的颜色选项,方便在代码中进行统一的颜色选择和判断,这里分别对应黄色、蓝色、白色、绿色、红色 - public static final int YELLOW = 0; - public static final int BLUE = 1; - public static final int WHITE = 2; - public static final int GREEN = 3; - public static final int RED = 4; - - // 定义默认的背景颜色常量,其值为黄色(对应上面定义的颜色常量中的YELLOW),表示在没有特殊设置时默认使用的背景颜色 + + // 定义笔记背景颜色的常量 + public static final int YELLOW = 0; + public static final int BLUE = 1; + public static final int WHITE = 2; + public static final int GREEN = 3; + public static final int RED = 4; + + // 默认笔记背景颜色 public static final int BG_DEFAULT_COLOR = YELLOW; - - // 定义文本大小相关的常量,用整数表示不同的文本大小选项,方便在代码中统一处理文本大小相关的设置和获取,这里分别对应小、中、大、超大文本尺寸 - public static final int TEXT_SMALL = 0; - public static final int TEXT_MEDIUM = 1; - public static final int TEXT_LARGE = 2; - public static final int TEXT_SUPER = 3; - - // 定义默认的字体大小常量,其值为中等大小(对应上面定义的文本大小常量中的TEXT_MEDIUM),表示在没有特殊设置时默认使用的字体大小 + + // 定义笔记文本大小的常量 + public static final int TEXT_SMALL = 0; + public static final int TEXT_MEDIUM = 1; + public static final int TEXT_LARGE = 2; + public static final int TEXT_SUPER = 3; + + // 默认笔记背景文本大小 public static final int BG_DEFAULT_FONT_SIZE = TEXT_MEDIUM; - - // 内部静态类NoteBgResources,用于管理笔记编辑界面相关的背景资源(图片资源) + + // 用于获取编辑笔记时的背景资源 public static class NoteBgResources { - // 定义一个私有的静态整型数组,存储笔记编辑界面背景图片资源的ID,对应不同颜色的编辑界面背景图片,顺序与前面定义的颜色常量顺序一致 - private final static int[] BG_EDIT_RESOURCES = new int[] { - R.drawable.edit_yellow, - R.drawable.edit_blue, - R.drawable.edit_white, - R.drawable.edit_green, - R.drawable.edit_red + private final static int [] BG_EDIT_RESOURCES = new int [] { + R.drawable.edit_yellow, + R.drawable.edit_blue, + R.drawable.edit_white, + R.drawable.edit_green, + R.drawable.edit_red }; - - // 定义一个私有的静态整型数组,存储笔记编辑界面标题背景图片资源的ID,对应不同颜色的编辑界面标题背景图片,顺序与前面定义的颜色常量顺序一致 - private final static int[] BG_EDIT_TITLE_RESOURCES = new int[] { - R.drawable.edit_title_yellow, - R.drawable.edit_title_blue, - R.drawable.edit_title_white, - R.drawable.edit_title_green, - R.drawable.edit_title_red + + private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] { + R.drawable.edit_title_yellow, + R.drawable.edit_title_blue, + R.drawable.edit_title_white, + R.drawable.edit_title_green, + R.drawable.edit_title_red }; - - // 根据传入的颜色ID(对应前面定义的颜色常量)获取笔记编辑界面的背景图片资源ID,方便在设置编辑界面背景时使用 + + // 根据ID获取编辑笔记的背景资源 public static int getNoteBgResource(int id) { return BG_EDIT_RESOURCES[id]; } - - // 根据传入的颜色ID(对应前面定义的颜色常量)获取笔记编辑界面标题的背景图片资源ID,方便在设置编辑界面标题背景时使用 + + // 根据ID获取编辑笔记标题的背景资源 public static int getNoteTitleBgResource(int id) { return BG_EDIT_TITLE_RESOURCES[id]; } } - - // 根据传入的上下文(Context)获取默认的背景图片ID,逻辑是先检查是否在偏好设置中设置了自定义背景颜色(通过特定的偏好设置键来判断), - // 如果设置了,则随机选择一个背景资源ID(从NoteBgResources中定义的资源数组长度范围内随机),否则返回默认的背景颜色ID(BG_DEFAULT_COLOR) + + // 获取默认笔记背景颜色ID public static int getDefaultBgId(Context context) { if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean( NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) { @@ -86,114 +81,106 @@ public class ResourceParser { return BG_DEFAULT_COLOR; } } - - // 内部静态类NoteItemBgResources,用于管理笔记列表项相关的背景资源(图片资源) + + // 用于获取笔记列表项的背景资源 public static class NoteItemBgResources { - // 定义一个私有的静态整型数组,存储笔记列表项第一个元素(可能是列表头部等情况)的背景图片资源ID,对应不同颜色的背景图片,顺序与前面定义的颜色常量顺序一致 - private final static int[] BG_FIRST_RESOURCES = new int[] { - R.drawable.list_yellow_up, - R.drawable.list_blue_up, - R.drawable.list_white_up, - R.drawable.list_green_up, - R.drawable.list_red_up + private final static int [] BG_FIRST_RESOURCES = new int [] { + R.drawable.list_yellow_up, + R.drawable.list_blue_up, + R.drawable.list_white_up, + R.drawable.list_green_up, + R.drawable.list_red_up }; - - // 定义一个私有的静态整型数组,存储笔记列表项中间元素(正常的列表项情况)的背景图片资源ID,对应不同颜色的背景图片,顺序与前面定义的颜色常量顺序一致 - private final static int[] BG_NORMAL_RESOURCES = new int[] { - R.drawable.list_yellow_middle, - R.drawable.list_blue_middle, - R.drawable.list_white_middle, - R.drawable.list_green_middle, - R.drawable.list_red_middle + + private final static int [] BG_NORMAL_RESOURCES = new int [] { + R.drawable.list_yellow_middle, + R.drawable.list_blue_middle, + R.drawable.list_white_middle, + R.drawable.list_green_middle, + R.drawable.list_red_middle, }; - - // 定义一个私有的静态整型数组,存储笔记列表项最后一个元素(可能是列表尾部等情况)的背景图片资源ID,对应不同颜色的背景图片,顺序与前面定义的颜色常量顺序一致 - private final static int[] BG_LAST_RESOURCES = new int[] { - R.drawable.list_yellow_down, - R.drawable.list_blue_down, - R.drawable.list_white_down, - R.drawable.list_green_down, - R.drawable.list_red_down, + + private final static int [] BG_LAST_RESOURCES = new int [] { + R.drawable.list_yellow_down, + R.drawable.list_blue_down, + R.drawable.list_white_down, + R.drawable.list_green_down, + R.drawable.list_red_down, }; - - // 定义一个私有的静态整型数组,存储单个笔记(可能是独立展示等情况)的背景图片资源ID,对应不同颜色的背景图片,顺序与前面定义的颜色常量顺序一致 - private final static int[] BG_SINGLE_RESOURCES = new int[] { - R.drawable.list_yellow_single, - R.drawable.list_blue_single, - R.drawable.list_white_single, - R.drawable.list_green_single, - R.drawable.list_red_single + + private final static int [] BG_SINGLE_RESOURCES = new int [] { + R.drawable.list_yellow_single, + R.drawable.list_blue_single, + R.drawable.list_white_single, + R.drawable.list_green_single, + R.drawable.list_red_single }; - - // 根据传入的颜色ID(对应前面定义的颜色常量)获取笔记列表项第一个元素的背景图片资源ID,方便在设置列表项背景时使用 + + // 根据ID获取笔记列表第一项的背景资源 public static int getNoteBgFirstRes(int id) { return BG_FIRST_RESOURCES[id]; } - - // 根据传入的颜色ID(对应前面定义的颜色常量)获取笔记列表项最后一个元素的背景图片资源ID,方便在设置列表项背景时使用 + + // 根据ID获取笔记列表最后一项的背景资源 public static int getNoteBgLastRes(int id) { return BG_LAST_RESOURCES[id]; } - - // 根据传入的颜色ID(对应前面定义的颜色常量)获取单个笔记的背景图片资源ID,方便在设置单个笔记背景时使用 + + // 根据ID获取单个笔记项的背景资源 public static int getNoteBgSingleRes(int id) { return BG_SINGLE_RESOURCES[id]; } - - // 根据传入的颜色ID(对应前面定义的颜色常量)获取笔记列表项中间元素(正常列表项)的背景图片资源ID,方便在设置列表项背景时使用 + + // 根据ID获取笔记列表中间项的背景资源 public static int getNoteBgNormalRes(int id) { return BG_NORMAL_RESOURCES[id]; } - - // 获取文件夹的背景图片资源ID,用于设置文件夹在列表等展示场景中的背景图片 + + // 获取文件夹背景资源 public static int getFolderBgRes() { return R.drawable.list_folder; } } - - // 内部静态类WidgetBgResources,用于管理桌面小部件相关的背景资源(图片资源) + + // 用于获取小部件的背景资源 public static class WidgetBgResources { - // 定义一个私有的静态整型数组,存储2x尺寸桌面小部件的背景图片资源ID,对应不同颜色的背景图片,顺序与前面定义的颜色常量顺序一致 - private final static int[] BG_2X_RESOURCES = new int[] { - R.drawable.widget_2x_yellow, - R.drawable.widget_2x_blue, - R.drawable.widget_2x_white, - R.drawable.widget_2x_green, - R.drawable.widget_2x_red, + private final static int [] BG_2X_RESOURCES = new int [] { + R.drawable.widget_2x_yellow, + R.drawable.widget_2x_blue, + R.drawable.widget_2x_white, + R.drawable.widget_2x_green, + R.drawable.widget_2x_red, }; - - // 根据传入的颜色ID(对应前面定义的颜色常量)获取2x尺寸桌面小部件的背景图片资源ID,方便在设置小部件背景时使用 + + // 根据ID获取2x小部件的背景资源 public static int getWidget2xBgResource(int id) { return BG_2X_RESOURCES[id]; } - - // 定义一个私有的静态整型数组,存储4x尺寸桌面小部件的背景图片资源ID,对应不同颜色的背景图片,顺序与前面定义的颜色常量顺序一致 - private final static int[] BG_4X_RESOURCES = new int[] { - R.drawable.widget_4x_yellow, - R.drawable.widget_4x_blue, - R.drawable.widget_4x_white, - R.drawable.widget_4x_green, - R.drawable.widget_4x_red + + private final static int [] BG_4X_RESOURCES = new int [] { + R.drawable.widget_4x_yellow, + R.drawable.widget_4x_blue, + R.drawable.widget_4x_white, + R.drawable.widget_4x_green, + R.drawable.widget_4x_red }; - - // 根据传入的颜色ID(对应前面定义的颜色常量)获取4x尺寸桌面小部件的背景图片资源ID,方便在设置小部件背景时使用 + + // 根据ID获取4x小部件的背景资源 public static int getWidget4xBgResource(int id) { return BG_4X_RESOURCES[id]; } } - - // 内部静态类TextAppearanceResources,用于管理文本外观相关的资源(主要是文本样式资源) + + // 用于获取文本外观资源 public static class TextAppearanceResources { - // 定义一个私有的静态整型数组,存储不同文本外观样式的资源ID,对应不同大小的文本外观样式,顺序与前面定义的文本大小常量顺序有一定关联 - private final static int[] TEXTAPPEARANCE_RESOURCES = new int[] { - R.style.TextAppearanceNormal, - R.style.TextAppearanceMedium, - R.style.TextAppearanceLarge, - R.style.TextAppearanceSuper + private final static int [] TEXTAPPEARANCE_RESOURCES = new int [] { + R.style.TextAppearanceNormal, + R.style.TextAppearanceMedium, + R.style.TextAppearanceLarge, + R.style.TextAppearanceSuper }; - - // 根据传入的文本外观资源ID获取对应的文本外观资源ID,如果传入的ID大于资源数组的长度(可能是由于存储或获取出现异常情况), - // 则返回默认的字体大小对应的资源ID(BG_DEFAULT_FONT_SIZE),以避免出现资源获取错误 + + // 根据ID获取文本外观资源 public static int getTexAppearanceResource(int id) { /** * HACKME: Fix bug of store the resource id in shared preference. @@ -205,8 +192,8 @@ public class ResourceParser { } return TEXTAPPEARANCE_RESOURCES[id]; } - - // 获取文本外观资源数组的长度,可用于判断资源数量或者进行一些边界相关的操作判断等 + + // 获取文本外观资源的数量 public static int getResourcesSize() { return TEXTAPPEARANCE_RESOURCES.length; } diff --git a/src/Notes-master/src/net/micode/notes/ui/AlarmAlertActivity.java b/src/Notes-master/src/net/micode/notes/ui/AlarmAlertActivity.java index 85723be..5f40071 100644 --- a/src/Notes-master/src/net/micode/notes/ui/AlarmAlertActivity.java +++ b/src/Notes-master/src/net/micode/notes/ui/AlarmAlertActivity.java @@ -39,21 +39,29 @@ import net.micode.notes.tool.DataUtils; import java.io.IOException; - +/** + * 闹钟提醒活动类,继承自Activity,实现了OnClickListener和OnDismissListener接口。 + * 该活动用于在闹钟响起时显示提醒对话框,并播放默认的闹钟声音。 + */ public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener { - private long mNoteId; - private String mSnippet; - private static final int SNIPPET_PREW_MAX_LEN = 60; - MediaPlayer mPlayer; - + private long mNoteId; // 保存笔记的ID + private String mSnippet; // 保存笔记的摘要 + private static final int SNIPPET_PREW_MAX_LEN = 60; // 笔记摘要的最大长度 + MediaPlayer mPlayer; // 用于播放闹钟声音的MediaPlayer实例 + + /** + * 创建活动时调用的方法。 + * @param savedInstanceState 保存的实例状态数据包 + */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - requestWindowFeature(Window.FEATURE_NO_TITLE); + requestWindowFeature(Window.FEATURE_NO_TITLE); // 请求无标题窗口 - final Window win = getWindow(); - win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); + final Window win = getWindow(); // 获取当前窗口 + win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); // 设置窗口在锁屏时显示 + // 如果屏幕未点亮,则添加更多标志以保持屏幕点亮并允许在锁屏时操作 if (!isScreenOn()) { win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON @@ -61,98 +69,123 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); } - Intent intent = getIntent(); + Intent intent = getIntent(); // 获取启动该活动的Intent try { - mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1)); - mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId); + mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1)); // 从Intent中提取笔记ID + mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId); // 根据笔记ID获取摘要 + // 如果摘要长度超过最大限制,则截取前SNIPPET_PREW_MAX_LEN个字符并添加省略号 mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN ? mSnippet.substring(0, SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info) : mSnippet; } catch (IllegalArgumentException e) { - e.printStackTrace(); - return; + e.printStackTrace(); // 打印异常信息 + return; // 如果发生异常,则结束该方法 } - mPlayer = new MediaPlayer(); + mPlayer = new MediaPlayer(); // 创建MediaPlayer实例 + // 检查数据库中是否存在指定ID的笔记 if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) { - showActionDialog(); - playAlarmSound(); + showActionDialog(); // 显示操作对话框 + playAlarmSound(); // 播放闹钟声音 } else { - finish(); + finish(); // 如果笔记不存在,则结束该活动 } } + /** + * 检查屏幕是否点亮。 + * @return 如果屏幕点亮则返回true,否则返回false + */ private boolean isScreenOn() { - PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); - return pm.isScreenOn(); + PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); // 获取电源管理服务 + return pm.isScreenOn(); // 返回屏幕是否点亮的状态 } + /** + * 播放闹钟声音的方法。 + */ private void playAlarmSound() { + // 获取实际的默认闹钟铃声URI Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM); + // 获取当前设置的静音模式影响的音频流类型 int silentModeStreams = Settings.System.getInt(getContentResolver(), Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); + // 如果静音模式影响了闹钟音频流,则设置MediaPlayer的音频流类型为silentModeStreams + // 否则,设置为AudioManager.STREAM_ALARM if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) { mPlayer.setAudioStreamType(silentModeStreams); } else { mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM); } try { - mPlayer.setDataSource(this, url); - mPlayer.prepare(); - mPlayer.setLooping(true); - mPlayer.start(); + mPlayer.setDataSource(this, url); // 设置MediaPlayer的数据源为闹钟铃声URI + mPlayer.prepare(); // 准备MediaPlayer + mPlayer.setLooping(true); // 设置MediaPlayer循环播放 + mPlayer.start(); // 开始播放闹钟声音 } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + e.printStackTrace(); // 打印异常信息 } catch (SecurityException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + e.printStackTrace(); // 打印异常信息 } catch (IllegalStateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + e.printStackTrace(); // 打印异常信息 } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + e.printStackTrace(); // 打印异常信息 } } + /** + * 显示操作对话框的方法。 + */ private void showActionDialog() { - AlertDialog.Builder dialog = new AlertDialog.Builder(this); - dialog.setTitle(R.string.app_name); - dialog.setMessage(mSnippet); - dialog.setPositiveButton(R.string.notealert_ok, this); + AlertDialog.Builder dialog = new AlertDialog.Builder(this); // 创建AlertDialog.Builder实例 + dialog.setTitle(R.string.app_name); // 设置对话框标题为应用名称 + dialog.setMessage(mSnippet); // 设置对话框消息为笔记摘要 + dialog.setPositiveButton(R.string.notealert_ok, this); // 设置确定按钮及其监听器 + // 如果屏幕已点亮,则添加进入按钮及其监听器 if (isScreenOn()) { dialog.setNegativeButton(R.string.notealert_enter, this); } - dialog.show().setOnDismissListener(this); + dialog.show().setOnDismissListener(this); // 显示对话框并设置对话框消失监听器 } + /** + * 实现OnClickListener接口的方法,处理对话框按钮点击事件。 + * @param dialog 触发点击事件的对话框 + * @param which 点击的按钮的ID + */ public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_NEGATIVE: - Intent intent = new Intent(this, NoteEditActivity.class); - intent.setAction(Intent.ACTION_VIEW); - intent.putExtra(Intent.EXTRA_UID, mNoteId); - startActivity(intent); + Intent intent = new Intent(this, NoteEditActivity.class); // 创建Intent准备跳转到笔记编辑活动 + intent.setAction(Intent.ACTION_VIEW); // 设置Intent动作类型为ACTION_VIEW + intent.putExtra(Intent.EXTRA_UID, mNoteId); // 添加笔记ID作为附加信息 + startActivity(intent); // 启动笔记编辑活动 break; default: break; } } + /** + * 实现OnDismissListener接口的方法,处理对话框消失事件。 + * @param dialog 消失的对话框 + */ public void onDismiss(DialogInterface dialog) { - stopAlarmSound(); - finish(); + stopAlarmSound(); // 停止播放闹钟声音 + finish(); // 结束该活动 } + /** + * 停止并释放MediaPlayer的方法。 + */ private void stopAlarmSound() { if (mPlayer != null) { - mPlayer.stop(); - mPlayer.release(); - mPlayer = null; + mPlayer.stop(); // 停止MediaPlayer播放 + mPlayer.release(); // 释放MediaPlayer资源 + mPlayer = null; // 将mPlayer置为null } } } diff --git a/src/Notes-master/src/net/micode/notes/ui/AlarmInitReceiver.java b/src/Notes-master/src/net/micode/notes/ui/AlarmInitReceiver.java index f221202..f8bb98a 100644 --- a/src/Notes-master/src/net/micode/notes/ui/AlarmInitReceiver.java +++ b/src/Notes-master/src/net/micode/notes/ui/AlarmInitReceiver.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.ui; - + import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; @@ -23,21 +23,24 @@ import android.content.ContentUris; import android.content.Context; import android.content.Intent; import android.database.Cursor; - + import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; - - + +// 该广播接收器用于初始化闹钟,查询即将提醒的笔记并设置闹钟 public class AlarmInitReceiver extends BroadcastReceiver { - + + // 查询笔记数据库时使用的列投影 private static final String [] PROJECTION = new String [] { NoteColumns.ID, NoteColumns.ALERTED_DATE }; - + + // 列索引常量,用于从查询结果中提取数据 private static final int COLUMN_ID = 0; private static final int COLUMN_ALERTED_DATE = 1; - + + // 接收广播时执行的方法,查询数据库并设置闹钟 @Override public void onReceive(Context context, Intent intent) { long currentDate = System.currentTimeMillis(); @@ -46,7 +49,7 @@ public class AlarmInitReceiver extends BroadcastReceiver { NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE, new String[] { String.valueOf(currentDate) }, null); - + if (c != null) { if (c.moveToFirst()) { do { @@ -62,4 +65,4 @@ public class AlarmInitReceiver extends BroadcastReceiver { c.close(); } } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/ui/AlarmReceiver.java b/src/Notes-master/src/net/micode/notes/ui/AlarmReceiver.java index 54e503b..3d2b949 100644 --- a/src/Notes-master/src/net/micode/notes/ui/AlarmReceiver.java +++ b/src/Notes-master/src/net/micode/notes/ui/AlarmReceiver.java @@ -13,18 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.ui; - + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; - + +// 一个继承自BroadcastReceiver的类,用于接收闹钟触发的广播 public class AlarmReceiver extends BroadcastReceiver { + // 当接收到广播时,该方法会被调用 @Override public void onReceive(Context context, Intent intent) { + // 设置Intent的目标Activity为AlarmAlertActivity intent.setClass(context, AlarmAlertActivity.class); + // 添加标志以允许启动新的Activity intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + // 启动AlarmAlertActivity context.startActivity(intent); } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/ui/DateTimePicker.java b/src/Notes-master/src/net/micode/notes/ui/DateTimePicker.java index 496b0cd..9601ff7 100644 --- a/src/Notes-master/src/net/micode/notes/ui/DateTimePicker.java +++ b/src/Notes-master/src/net/micode/notes/ui/DateTimePicker.java @@ -1,485 +1,745 @@ -/* - * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.micode.notes.ui; - -import java.text.DateFormatSymbols; -import java.util.Calendar; - -import net.micode.notes.R; - - -import android.content.Context; -import android.text.format.DateFormat; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.NumberPicker; - -public class DateTimePicker extends FrameLayout { - - private static final boolean DEFAULT_ENABLE_STATE = true; - - private static final int HOURS_IN_HALF_DAY = 12; - private static final int HOURS_IN_ALL_DAY = 24; - private static final int DAYS_IN_ALL_WEEK = 7; - private static final int DATE_SPINNER_MIN_VAL = 0; - private static final int DATE_SPINNER_MAX_VAL = DAYS_IN_ALL_WEEK - 1; - private static final int HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW = 0; - private static final int HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW = 23; - private static final int HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW = 1; - private static final int HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW = 12; - private static final int MINUT_SPINNER_MIN_VAL = 0; - private static final int MINUT_SPINNER_MAX_VAL = 59; - private static final int AMPM_SPINNER_MIN_VAL = 0; - private static final int AMPM_SPINNER_MAX_VAL = 1; - - private final NumberPicker mDateSpinner; - private final NumberPicker mHourSpinner; - private final NumberPicker mMinuteSpinner; - private final NumberPicker mAmPmSpinner; - private Calendar mDate; - - private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK]; - - private boolean mIsAm; - - private boolean mIs24HourView; - - private boolean mIsEnabled = DEFAULT_ENABLE_STATE; - - private boolean mInitialising; - - private OnDateTimeChangedListener mOnDateTimeChangedListener; - - 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(); - } - }; - - private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() { - @Override - public void onValueChange(NumberPicker picker, int oldVal, int newVal) { - boolean isDateChanged = false; - Calendar cal = Calendar.getInstance(); - if (!mIs24HourView) { - if (!mIsAm && oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) { - cal.setTimeInMillis(mDate.getTimeInMillis()); - cal.add(Calendar.DAY_OF_YEAR, 1); - isDateChanged = true; - } else if (mIsAm && oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) { - cal.setTimeInMillis(mDate.getTimeInMillis()); - cal.add(Calendar.DAY_OF_YEAR, -1); - isDateChanged = true; - } - if (oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY || - oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) { - mIsAm = !mIsAm; - updateAmPmControl(); - } - } else { - if (oldVal == HOURS_IN_ALL_DAY - 1 && newVal == 0) { - cal.setTimeInMillis(mDate.getTimeInMillis()); - cal.add(Calendar.DAY_OF_YEAR, 1); - isDateChanged = true; - } else if (oldVal == 0 && newVal == HOURS_IN_ALL_DAY - 1) { - cal.setTimeInMillis(mDate.getTimeInMillis()); - cal.add(Calendar.DAY_OF_YEAR, -1); - isDateChanged = true; - } - } - int newHour = mHourSpinner.getValue() % HOURS_IN_HALF_DAY + (mIsAm ? 0 : HOURS_IN_HALF_DAY); - mDate.set(Calendar.HOUR_OF_DAY, newHour); - onDateTimeChanged(); - if (isDateChanged) { - setCurrentYear(cal.get(Calendar.YEAR)); - setCurrentMonth(cal.get(Calendar.MONTH)); - setCurrentDay(cal.get(Calendar.DAY_OF_MONTH)); - } - } - }; - - private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() { - @Override - public void onValueChange(NumberPicker picker, int oldVal, int newVal) { - int minValue = mMinuteSpinner.getMinValue(); - int maxValue = mMinuteSpinner.getMaxValue(); - int offset = 0; - if (oldVal == maxValue && newVal == minValue) { - offset += 1; - } else if (oldVal == minValue && newVal == maxValue) { - offset -= 1; - } - if (offset != 0) { - mDate.add(Calendar.HOUR_OF_DAY, offset); - mHourSpinner.setValue(getCurrentHour()); - updateDateControl(); - int newHour = getCurrentHourOfDay(); - if (newHour >= HOURS_IN_HALF_DAY) { - mIsAm = false; - updateAmPmControl(); - } else { - mIsAm = true; - updateAmPmControl(); - } - } - mDate.set(Calendar.MINUTE, newVal); - onDateTimeChanged(); - } - }; - - private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() { - @Override - public void onValueChange(NumberPicker picker, int oldVal, int newVal) { - mIsAm = !mIsAm; - if (mIsAm) { - mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY); - } else { - mDate.add(Calendar.HOUR_OF_DAY, HOURS_IN_HALF_DAY); - } - updateAmPmControl(); - onDateTimeChanged(); - } - }; - - public interface OnDateTimeChangedListener { - void onDateTimeChanged(DateTimePicker view, int year, int month, - int dayOfMonth, int hourOfDay, int minute); - } - - public DateTimePicker(Context context) { - this(context, System.currentTimeMillis()); - } - - public DateTimePicker(Context context, long date) { - this(context, date, DateFormat.is24HourFormat(context)); - } - - 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); - - mDateSpinner = (NumberPicker) findViewById(R.id.date); - mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL); - mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL); - mDateSpinner.setOnValueChangedListener(mOnDateChangedListener); - - mHourSpinner = (NumberPicker) findViewById(R.id.hour); - mHourSpinner.setOnValueChangedListener(mOnHourChangedListener); - mMinuteSpinner = (NumberPicker) findViewById(R.id.minute); - mMinuteSpinner.setMinValue(MINUT_SPINNER_MIN_VAL); - mMinuteSpinner.setMaxValue(MINUT_SPINNER_MAX_VAL); - mMinuteSpinner.setOnLongPressUpdateInterval(100); - mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener); - - String[] stringsForAmPm = new DateFormatSymbols().getAmPmStrings(); - mAmPmSpinner = (NumberPicker) findViewById(R.id.amPm); - mAmPmSpinner.setMinValue(AMPM_SPINNER_MIN_VAL); - mAmPmSpinner.setMaxValue(AMPM_SPINNER_MAX_VAL); - mAmPmSpinner.setDisplayedValues(stringsForAmPm); - mAmPmSpinner.setOnValueChangedListener(mOnAmPmChangedListener); - - // update controls to initial state - updateDateControl(); - updateHourControl(); - updateAmPmControl(); - - set24HourView(is24HourView); - - // set to current time - setCurrentDate(date); - - setEnabled(isEnabled()); - - // set the content descriptions - mInitialising = false; - } - - @Override - public void setEnabled(boolean enabled) { - if (mIsEnabled == enabled) { - return; - } - super.setEnabled(enabled); - mDateSpinner.setEnabled(enabled); - mMinuteSpinner.setEnabled(enabled); - mHourSpinner.setEnabled(enabled); - mAmPmSpinner.setEnabled(enabled); - mIsEnabled = enabled; - } - - @Override - public boolean isEnabled() { - return mIsEnabled; - } - - /** - * Get the current date in millis - * - * @return the current date in millis - */ - public long getCurrentDateInTimeMillis() { - return mDate.getTimeInMillis(); - } - - /** - * Set the current date - * - * @param date The current date in millis - */ - public void setCurrentDate(long date) { - Calendar cal = Calendar.getInstance(); - cal.setTimeInMillis(date); - setCurrentDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), - cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)); - } - - /** - * Set the current date - * - * @param year The current year - * @param month The current month - * @param dayOfMonth The current dayOfMonth - * @param hourOfDay The current hourOfDay - * @param minute The current minute - */ - public void setCurrentDate(int year, int month, - int dayOfMonth, int hourOfDay, int minute) { - setCurrentYear(year); - setCurrentMonth(month); - setCurrentDay(dayOfMonth); - setCurrentHour(hourOfDay); - setCurrentMinute(minute); - } - - /** - * Get current year - * - * @return The current year - */ - public int getCurrentYear() { - return mDate.get(Calendar.YEAR); - } - - /** - * Set current year - * - * @param year The current year - */ - public void setCurrentYear(int year) { - if (!mInitialising && year == getCurrentYear()) { - return; - } - mDate.set(Calendar.YEAR, year); - updateDateControl(); - onDateTimeChanged(); - } - - /** - * Get current month in the year - * - * @return The current month in the year - */ - public int getCurrentMonth() { - return mDate.get(Calendar.MONTH); - } - - /** - * Set current month in the year - * - * @param month The month in the year - */ - public void setCurrentMonth(int month) { - if (!mInitialising && month == getCurrentMonth()) { - return; - } - mDate.set(Calendar.MONTH, month); - updateDateControl(); - onDateTimeChanged(); - } - - /** - * Get current day of the month - * - * @return The day of the month - */ - public int getCurrentDay() { - return mDate.get(Calendar.DAY_OF_MONTH); - } - - /** - * Set current day of the month - * - * @param dayOfMonth The day of the month - */ - public void setCurrentDay(int dayOfMonth) { - if (!mInitialising && dayOfMonth == getCurrentDay()) { - return; - } - mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); - updateDateControl(); - onDateTimeChanged(); - } - - /** - * Get current hour in 24 hour mode, in the range (0~23) - * @return The current hour in 24 hour mode - */ - public int getCurrentHourOfDay() { - return mDate.get(Calendar.HOUR_OF_DAY); - } - - private int getCurrentHour() { - if (mIs24HourView){ - return getCurrentHourOfDay(); - } else { - int hour = getCurrentHourOfDay(); - if (hour > HOURS_IN_HALF_DAY) { - return hour - HOURS_IN_HALF_DAY; - } else { - return hour == 0 ? HOURS_IN_HALF_DAY : hour; - } - } - } - - /** - * Set current hour in 24 hour mode, in the range (0~23) - * - * @param hourOfDay - */ - public void setCurrentHour(int hourOfDay) { - if (!mInitialising && hourOfDay == getCurrentHourOfDay()) { - return; - } - mDate.set(Calendar.HOUR_OF_DAY, hourOfDay); - if (!mIs24HourView) { - if (hourOfDay >= HOURS_IN_HALF_DAY) { - mIsAm = false; - if (hourOfDay > HOURS_IN_HALF_DAY) { - hourOfDay -= HOURS_IN_HALF_DAY; - } - } else { - mIsAm = true; - if (hourOfDay == 0) { - hourOfDay = HOURS_IN_HALF_DAY; - } - } - updateAmPmControl(); - } - mHourSpinner.setValue(hourOfDay); - onDateTimeChanged(); - } - - /** - * Get currentMinute - * - * @return The Current Minute - */ - public int getCurrentMinute() { - return mDate.get(Calendar.MINUTE); - } - - /** - * Set current minute - */ - public void setCurrentMinute(int minute) { - if (!mInitialising && minute == getCurrentMinute()) { - return; - } - mMinuteSpinner.setValue(minute); - mDate.set(Calendar.MINUTE, minute); - onDateTimeChanged(); - } - - /** - * @return true if this is in 24 hour view else false. - */ - public boolean is24HourView () { - return mIs24HourView; - } - - /** - * Set whether in 24 hour or AM/PM mode. - * - * @param is24HourView True for 24 hour mode. False for AM/PM mode. - */ - public void set24HourView(boolean is24HourView) { - if (mIs24HourView == is24HourView) { - return; - } - mIs24HourView = is24HourView; - mAmPmSpinner.setVisibility(is24HourView ? View.GONE : View.VISIBLE); - int hour = getCurrentHourOfDay(); - updateHourControl(); - setCurrentHour(hour); - updateAmPmControl(); - } - - private void updateDateControl() { - Calendar cal = Calendar.getInstance(); - cal.setTimeInMillis(mDate.getTimeInMillis()); - cal.add(Calendar.DAY_OF_YEAR, -DAYS_IN_ALL_WEEK / 2 - 1); - mDateSpinner.setDisplayedValues(null); - for (int i = 0; i < DAYS_IN_ALL_WEEK; ++i) { - cal.add(Calendar.DAY_OF_YEAR, 1); - mDateDisplayValues[i] = (String) DateFormat.format("MM.dd EEEE", cal); - } - mDateSpinner.setDisplayedValues(mDateDisplayValues); - mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2); - mDateSpinner.invalidate(); - } - - private void updateAmPmControl() { - if (mIs24HourView) { - mAmPmSpinner.setVisibility(View.GONE); - } else { - int index = mIsAm ? Calendar.AM : Calendar.PM; - mAmPmSpinner.setValue(index); - mAmPmSpinner.setVisibility(View.VISIBLE); - } - } - - private void updateHourControl() { - if (mIs24HourView) { - mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW); - mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW); - } else { - mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW); - mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW); - } - } - - /** - * Set the callback that indicates the 'Set' button has been pressed. - * @param callback the callback, if null will do nothing - */ - public void setOnDateTimeChangedListener(OnDateTimeChangedListener callback) { - mOnDateTimeChangedListener = callback; - } - - private void onDateTimeChanged() { - if (mOnDateTimeChangedListener != null) { - mOnDateTimeChangedListener.onDateTimeChanged(this, getCurrentYear(), - getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute()); - } - } -} +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.ui; + +import java.text.DateFormatSymbols; +import java.util.Calendar; + +import net.micode.notes.R; + +import android.content.Context; +import android.text.format.DateFormat; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.NumberPicker; + +// DateTimePicker类继承自FrameLayout,用于显示日期和时间选择控件 +public class DateTimePicker extends FrameLayout { + + // 默认控件是否可用 + private static final boolean DEFAULT_ENABLE_STATE = true; + + // 半天中的小时数、全天中的小时数、一周中的天数等常量 + private static final int HOURS_IN_HALF_DAY = 12; + private static final int HOURS_IN_ALL_DAY = 24; + private static final int DAYS_IN_ALL_WEEK = 7; + private static final int DATE_SPINNER_MIN_VAL = 0; + private static final int DATE_SPINNER_MAX_VAL = DAYS_IN_ALL_WEEK - 1; + private static final int HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW = 0; + private static final int HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW = 23; + private static final int HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW = 1; + private static final int HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW = 12; + private static final int MINUT_SPINNER_MIN_VAL = 0; + private static final int MINUT_SPINNER_MAX_VAL = 59; + private static final int AMPM_SPINNER_MIN_VAL = 0; + private static final int AMPM_SPINNER_MAX_VAL = 1; + + // 日期、小时、分钟、AM/PM选择器控件 + private final NumberPicker mDateSpinner; + private final NumberPicker mHourSpinner; + private final NumberPicker mMinuteSpinner; + private final NumberPicker mAmPmSpinner; + // 当前日期时间 + private Calendar mDate; + + // 日期显示值数组 + private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK]; + + // 当前是否为AM + private boolean mIsAm; + + // 是否为24小时制视图 + private boolean mIs24HourView; + + // 控件是否可用 + private boolean mIsEnabled = DEFAULT_ENABLE_STATE; + + // 初始化标志 + private boolean mInitialising; + + // 日期时间改变监听器 + private OnDateTimeChangedListener mOnDateTimeChangedListener; + + // 日期选择器值改变监听器 + 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(); + } + }; + + // 小时选择器值改变监听器 + private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + boolean isDateChanged = false; + Calendar cal = Calendar.getInstance(); + if (!mIs24HourView) { + if (!mIsAm && oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, 1); + isDateChanged = true; + } else if (mIsAm && oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -1); + isDateChanged = true; + } + if (oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY || + oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) { + mIsAm = !mIsAm; + updateAmPmControl(); + } + } else { + if (oldVal == HOURS_IN_ALL_DAY - 1 && newVal == 0) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, 1); + isDateChanged = true; + } else if (oldVal == 0 && newVal == HOURS_IN_ALL_DAY - 1) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -1); + isDateChanged = true; + } + } + int newHour = mHourSpinner.getValue() % HOURS_IN_HALF_DAY + (mIsAm ? 0 : HOURS_IN_HALF_DAY); + mDate.set(Calendar.HOUR_OF_DAY, newHour); + onDateTimeChanged(); + if (isDateChanged) { + setCurrentYear(cal.get(Calendar.YEAR)); + setCurrentMonth(cal.get(Calendar.MONTH)); + setCurrentDay(cal.get(Calendar.DAY_OF_MONTH)); + } + } + }; + + // 分钟选择器值改变监听器 + private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + int minValue = mMinuteSpinner.getMinValue(); + int maxValue = mMinuteSpinner.getMaxValue(); + int offset = 0; + if (oldVal == maxValue && newVal == minValue) { + offset += 1; + } else if (oldVal == minValue && newVal == maxValue) { + offset -= 1; + } + if (offset != 0) { + mDate.add(Calendar.HOUR_OF_DAY, offset); + mHourSpinner.setValue(getCurrentHour()); + updateDateControl(); + int newHour = getCurrentHourOfDay(); + if (newHour >= HOURS_IN_HALF_DAY) { + mIsAm = false; + updateAmPmControl(); + } else { + mIsAm = true; + updateAmPmControl(); + } + } + mDate.set(Calendar.MINUTE, newVal); + onDateTimeChanged(); + } + }; + + // AM/PM选择器值改变监听器 + private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + mIsAm = !mIsAm; + if (mIsAm) { + mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY); + } else { + mDate.add(Calendar.HOUR_OF_DAY, HOURS_IN_HALF_DAY); + } + updateAmPmControl(); + onDateTimeChanged(); + } + }; + + // 日期时间改变监听器接口 + public interface OnDateTimeChangedListener { + void onDateTimeChanged(DateTimePicker view, int year, int month, + int dayOfMonth, int hourOfDay, int minute); + } + + // 构造函数,默认使用当前时间 + public DateTimePicker(Context context) { + this(context, System.currentTimeMillis()); + } + + // 构造函数,使用指定时间 + public DateTimePicker(Context context, long date) { + this(context, date, DateFormat.is24HourFormat(context)); + } + + // 构造函数,使用指定时间和是否为24小时制 + 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); + + mDateSpinner = (NumberPicker) findViewById(R.id.date); + mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL); + mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL); + mDateSpinner.setOnValueChangedListener(mOnDateChangedListener); + + mHourSpinner = (NumberPicker) findViewById(R.id.hour); + mHourSpinner.setOnValueChangedListener(mOnHourChangedListener); + mMinuteSpinner = (NumberPicker) findViewById(R.id.minute); + mMinuteSpinner.setMinValue(MINUT_SPINNER_MIN_VAL); + mMinuteSpinner.setMaxValue(MINUT_SPINNER_MAX_VAL); + mMinuteSpinner.setOnLongPressUpdateInterval(100); + mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener); + + String[] stringsForAmPm = new DateFormatSymbols().getAmPmStrings(); + mAmPmSpinner = (NumberPicker) findViewById(R.id.amPm); + mAmPmSpinner.setMinValue(AMPM_SPINNER_MIN_VAL); + mAmPmSpinner.setMaxValue(AMPM_SPINNER_MAX_VAL); + mAmPmSpinner.setDisplayedValues(stringsForAmPm); + mAmPmSpinner.setOnValueChangedListener(mOnAmPmChangedListener); + + // 更新控件到初始状态 + updateDateControl(); + updateHourControl(); + updateAmPmControl(); + + set24HourView(is24HourView); + + // 设置到当前时间 + setCurrentDate(date); + + setEnabled(isEnabled()); + + // 设置内容描述 + mInitialising = false; + } + + // 设置控件是否可用 + @Override + public void setEnabled(boolean enabled) { + if (mIsEnabled == enabled) { + return; + } + super.setEnabled(enabled); + mDateSpinner.setEnabled(enabled); + mMinuteSpinner.setEnabled(enabled); + mHourSpinner.setEnabled(enabled); + mAmPmSpinner.setEnabled(enabled); + mIsEnabled = enabled; + } + + // 获取控件是否可用 + @Override + public boolean isEnabled() { + return mIsEnabled; + } + + + +``` +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.ui; + +import java.text.DateFormatSymbols; +import java.util.Calendar; + +import net.micode.notes.R; + + +import android.content.Context; +import android.text.format.DateFormat; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.NumberPicker; + +/** + * DateTimePicker 类用于显示和选择日期和时间。 + */ +public class DateTimePicker extends FrameLayout { + + private static final boolean DEFAULT_ENABLE_STATE = true; + + private static final int HOURS_IN_HALF_DAY = 12; + private static final int HOURS_IN_ALL_DAY = 24; + private static final int DAYS_IN_ALL_WEEK = 7; + private static final int DATE_SPINNER_MIN_VAL = 0; + private static final int DATE_SPINNER_MAX_VAL = DAYS_IN_ALL_WEEK - 1; + private static final int HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW = 0; + private static final int HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW = 23; + private static final int HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW = 1; + private static final int HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW = 12; + private static final int MINUT_SPINNER_MIN_VAL = 0; + private static final int MINUT_SPINNER_MAX_VAL = 59; + private static final int AMPM_SPINNER_MIN_VAL = 0; + private static final int AMPM_SPINNER_MAX_VAL = 1; + + private final NumberPicker mDateSpinner; + private final NumberPicker mHourSpinner; + private final NumberPicker mMinuteSpinner; + private final NumberPicker mAmPmSpinner; + private Calendar mDate; + + private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK]; + + private boolean mIsAm; + + private boolean mIs24HourView; + + private boolean mIsEnabled = DEFAULT_ENABLE_STATE; + + private boolean mInitialising; + + private OnDateTimeChangedListener mOnDateTimeChangedListener; + + 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(); + } + }; + + private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + boolean isDateChanged = false; + Calendar cal = Calendar.getInstance(); + if (!mIs24HourView) { + if (!mIsAm && oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, 1); + isDateChanged = true; + } else if (mIsAm && oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -1); + isDateChanged = true; + } + if (oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY || + oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) { + mIsAm = !mIsAm; + updateAmPmControl(); + } + } else { + if (oldVal == HOURS_IN_ALL_DAY - 1 && newVal == 0) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, 1); + isDateChanged = true; + } else if (oldVal == 0 && newVal == HOURS_IN_ALL_DAY - 1) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -1); + isDateChanged = true; + } + } + int newHour = mHourSpinner.getValue() % HOURS_IN_HALF_DAY + (mIsAm ? 0 : HOURS_IN_HALF_DAY); + mDate.set(Calendar.HOUR_OF_DAY, newHour); + onDateTimeChanged(); + if (isDateChanged) { + setCurrentYear(cal.get(Calendar.YEAR)); + setCurrentMonth(cal.get(Calendar.MONTH)); + setCurrentDay(cal.get(Calendar.DAY_OF_MONTH)); + } + } + }; + + private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + int minValue = mMinuteSpinner.getMinValue(); + int maxValue = mMinuteSpinner.getMaxValue(); + int offset = 0; + if (oldVal == maxValue && newVal == minValue) { + offset += 1; + } else if (oldVal == minValue && newVal == maxValue) { + offset -= 1; + } + if (offset != 0) { + mDate.add(Calendar.HOUR_OF_DAY, offset); + mHourSpinner.setValue(getCurrentHour()); + updateDateControl(); + int newHour = getCurrentHourOfDay(); + if (newHour >= HOURS_IN_HALF_DAY) { + mIsAm = false; + updateAmPmControl(); + } else { + mIsAm = true; + updateAmPmControl(); + } + } + mDate.set(Calendar.MINUTE, newVal); + onDateTimeChanged(); + } + }; + + private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + mIsAm = !mIsAm; + if (mIsAm) { + mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY); + } else { + mDate.add(Calendar.HOUR_OF_DAY, HOURS_IN_HALF_DAY); + } + updateAmPmControl(); + onDateTimeChanged(); + } + }; + + /** + * OnDateTimeChangedListener 接口用于监听日期和时间的变化。 + */ + public interface OnDateTimeChangedListener { + void onDateTimeChanged(DateTimePicker view, int year, int month, + int dayOfMonth, int hourOfDay, int minute); + } + + /** + * 构造函数,使用当前时间初始化 DateTimePicker。 + */ + public DateTimePicker(Context context) { + this(context, System.currentTimeMillis()); + } + + /** + * 构造函数,使用指定时间初始化 DateTimePicker。 + */ + public DateTimePicker(Context context, long date) { + this(context, date, DateFormat.is24HourFormat(context)); + } + + /** + * 构造函数,使用指定时间和24小时制设置初始化 DateTimePicker。 + */ + 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); + + mDateSpinner = (NumberPicker) findViewById(R.id.date); + mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL); + mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL); + mDateSpinner.setOnValueChangedListener(mOnDateChangedListener); + + mHourSpinner = (NumberPicker) findViewById(R.id.hour); + mHourSpinner.setOnValueChangedListener(mOnHourChangedListener); + mMinuteSpinner = (NumberPicker) findViewById(R.id.minute); + mMinuteSpinner.setMinValue(MINUT_SPINNER_MIN_VAL); + mMinuteSpinner.setMaxValue(MINUT_SPINNER_MAX_VAL); + mMinuteSpinner.setOnLongPressUpdateInterval(100); + mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener); + + String[] stringsForAmPm = new DateFormatSymbols().getAmPmStrings(); + mAmPmSpinner = (NumberPicker) findViewById(R.id.amPm); + mAmPmSpinner.setMinValue(AMPM_SPINNER_MIN_VAL); + mAmPmSpinner.setMaxValue(AMPM_SPINNER_MAX_VAL); + mAmPmSpinner.setDisplayedValues(stringsForAmPm); + mAmPmSpinner.setOnValueChangedListener(mOnAmPmChangedListener); + + // 更新控件到初始状态 + updateDateControl(); + updateHourControl(); + updateAmPmControl(); + + set24HourView(is24HourView); + + // 设置为当前时间 + setCurrentDate(date); + + setEnabled(isEnabled()); + + // 设置内容描述 + mInitialising = false; + } + + /** + * 设置控件是否启用。 + */ + @Override + public void setEnabled(boolean enabled) { + if (mIsEnabled == enabled) { + return; + } + super.setEnabled(enabled); + mDateSpinner.setEnabled(enabled); + mMinuteSpinner.setEnabled(enabled); + mHourSpinner.setEnabled(enabled); + mAmPmSpinner.setEnabled(enabled); + mIsEnabled = enabled; + } + + /** + * 获取控件是否启用。 + */ + @Override + public boolean isEnabled() { + return mIsEnabled; + } + + /** + * 获取当前日期的毫秒数。 + */ + public long getCurrentDateInTimeMillis() { + return mDate.getTimeInMillis(); + } + + /** + * 设置当前日期。 + */ + public void setCurrentDate(long date) { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(date); + setCurrentDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), + cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)); + } + + /** + * 设置当前日期。 + */ + public void setCurrentDate(int year, int month, + int dayOfMonth, int hourOfDay, int minute) { + setCurrentYear(year); + setCurrentMonth(month); + setCurrentDay(dayOfMonth); + setCurrentHour(hourOfDay); + setCurrentMinute(minute); + } + + /** + * 获取当前年份。 + */ + public int getCurrentYear() { + return mDate.get(Calendar.YEAR); + } + + /** + * 设置当前年份。 + */ + public void setCurrentYear(int year) { + if (!mInitialising && year == getCurrentYear()) { + return; + } + mDate.set(Calendar.YEAR, year); + updateDateControl(); + onDateTimeChanged(); + } + + /** + * 获取当前月份。 + */ + public int getCurrentMonth() { + return mDate.get(Calendar.MONTH); + } + + /** + * 设置当前月份。 + */ + public void setCurrentMonth(int month) { + if (!mInitialising && month == getCurrentMonth()) { + return; + } + mDate.set(Calendar.MONTH, month); + updateDateControl(); + onDateTimeChanged(); + } + + /** + * 获取当前日期。 + */ + public int getCurrentDay() { + return mDate.get(Calendar.DAY_OF_MONTH); + } + + /** + * 设置当前日期。 + */ + public void setCurrentDay(int dayOfMonth) { + if (!mInitialising && dayOfMonth == getCurrentDay()) { + return; + } + mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); + updateDateControl(); + onDateTimeChanged(); + } + + /** + * 获取当前小时(24小时制)。 + */ + public int getCurrentHourOfDay() { + return mDate.get(Calendar.HOUR_OF_DAY); + } + + private int getCurrentHour() { + if (mIs24HourView){ + return getCurrentHourOfDay(); + } else { + int hour = getCurrentHourOfDay(); + if (hour > HOURS_IN_HALF_DAY) { + return hour - HOURS_IN_HALF_DAY; + } else { + return hour == 0 ? HOURS_IN_HALF_DAY : hour; + } + } + } + + /** + * 设置当前小时(24小时制)。 + */ + public void setCurrentHour(int hourOfDay) { + if (!mInitialising && hourOfDay == getCurrentHourOfDay()) { + return; + } + mDate.set(Calendar.HOUR_OF_DAY, hourOfDay); + if (!mIs24HourView) { + if (hourOfDay >= HOURS_IN_HALF_DAY) { + mIsAm = false; + if (hourOfDay > HOURS_IN_HALF_DAY) { + hourOfDay -= HOURS_IN_HALF_DAY; + } + } else { + mIsAm = true; + if (hourOfDay == 0) { + hourOfDay = HOURS_IN_HALF_DAY; + } + } + updateAmPmControl(); + } + mHourSpinner.setValue(hourOfDay); + onDateTimeChanged(); + } + + /** + * 获取当前分钟。 + */ + public int getCurrentMinute() { + return mDate.get(Calendar.MINUTE); + } + + /** + * 设置当前分钟。 + */ + public void setCurrentMinute(int minute) { + if (!mInitialising && minute == getCurrentMinute()) { + return; + } + mMinuteSpinner.setValue(minute); + mDate.set(Calendar.MINUTE, minute); + onDateTimeChanged(); + } + + /** + * 判断是否为24小时制。 + */ + public boolean is24HourView () { + return mIs24HourView; + } + + /** + * 设置是否为24小时制。 + */ + public void set24HourView(boolean is24HourView) { + if (mIs24HourView == is24HourView) { + return; + } + mIs24HourView = is24HourView; + mAmPmSpinner.setVisibility(is24HourView ? View.GONE : View.VISIBLE); + int hour = getCurrentHourOfDay(); + updateHourControl(); + setCurrentHour(hour); + updateAmPmControl(); + } + + /** + * 更新日期控件的显示。 + */ + private void updateDateControl() { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -DAYS_IN_ALL_WEEK / 2 - 1); + mDateSpinner.setDisplayedValues(null); + for (int i = 0; i < DAYS_IN_ALL_WEEK; ++i) { + cal.add(Calendar.DAY_OF_YEAR, 1); + mDateDisplayValues[i] = (String) DateFormat.format("MM.dd EEEE", cal); + } + mDateSpinner.setDisplayedValues(mDateDisplayValues); + mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2); + mDateSpinner.invalidate(); + } + + /** + * 更新AM/PM控件的显示。 + */ + private void updateAmPmControl() { + if (mIs24HourView) { + mAmPmSpinner.setVisibility(View.GONE); + } else { + int index = mIsAm ? Calendar.AM : Calendar.PM; + mAmPmSpinner.setValue(index); + mAmPmSpinner.setVisibility(View.VISIBLE); + } + } + + /** + * 更新小时控件的显示。 + */ + private void updateHourControl() { + if (mIs24HourView) { + mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW); + mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW); + } else { + mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW); + mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW); + } + } + + /** + * 设置日期时间变化的监听器。 + */ + public void setOnDateTimeChangedListener(OnDateTimeChangedListener callback) { + mOnDateTimeChangedListener = callback; + } + + /** + * 当日期或时间发生变化时调用此方法。 + */ + private void onDateTimeChanged() { + if (mOnDateTimeChangedListener != null) { + mOnDateTimeChangedListener.onDateTimeChanged(this, getCurrentYear(), + getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute()); + } + } +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/ui/DateTimePickerDialog.java b/src/Notes-master/src/net/micode/notes/ui/DateTimePickerDialog.java index 2c47ba4..e3c2eb4 100644 --- a/src/Notes-master/src/net/micode/notes/ui/DateTimePickerDialog.java +++ b/src/Notes-master/src/net/micode/notes/ui/DateTimePickerDialog.java @@ -13,33 +13,40 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.ui; - + import java.util.Calendar; - + import net.micode.notes.R; import net.micode.notes.ui.DateTimePicker; import net.micode.notes.ui.DateTimePicker.OnDateTimeChangedListener; - + import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.text.format.DateFormat; import android.text.format.DateUtils; - + +// 自定义的日期时间选择对话框,继承自AlertDialog并实现了OnClickListener接口 public class DateTimePickerDialog extends AlertDialog implements OnClickListener { - + + // 存储当前选择的日期时间 private Calendar mDate = Calendar.getInstance(); + // 是否使用24小时制 private boolean mIs24HourView; + // 回调接口,当日期时间设置完成后调用 private OnDateTimeSetListener mOnDateTimeSetListener; + // 日期时间选择器控件 private DateTimePicker mDateTimePicker; - + + // 定义日期时间设置完成后的回调接口 public interface OnDateTimeSetListener { void OnDateTimeSet(AlertDialog dialog, long date); } - + + // 构造函数,初始化对话框并设置初始日期时间 public DateTimePickerDialog(Context context, long date) { super(context); mDateTimePicker = new DateTimePicker(context); @@ -63,15 +70,18 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener set24HourView(DateFormat.is24HourFormat(this.getContext())); updateTitle(mDate.getTimeInMillis()); } - + + // 设置是否使用24小时制显示时间 public void set24HourView(boolean is24HourView) { mIs24HourView = is24HourView; } - + + // 设置日期时间选择完成后的回调监听器 public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) { mOnDateTimeSetListener = callBack; } - + + // 更新对话框的标题以显示当前选择的日期时间 private void updateTitle(long date) { int flag = DateUtils.FORMAT_SHOW_YEAR | @@ -80,11 +90,12 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR; setTitle(DateUtils.formatDateTime(this.getContext(), date, flag)); } - + + // 处理用户点击对话框按钮的事件,如果是确认按钮则调用回调监听器 public void onClick(DialogInterface arg0, int arg1) { if (mOnDateTimeSetListener != null) { mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis()); } } - + } \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/ui/DropdownMenu.java b/src/Notes-master/src/net/micode/notes/ui/DropdownMenu.java index 613dc74..eb009a2 100644 --- a/src/Notes-master/src/net/micode/notes/ui/DropdownMenu.java +++ b/src/Notes-master/src/net/micode/notes/ui/DropdownMenu.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.ui; - + import android.content.Context; import android.view.Menu; import android.view.MenuItem; @@ -24,14 +24,16 @@ import android.view.View.OnClickListener; import android.widget.Button; import android.widget.PopupMenu; import android.widget.PopupMenu.OnMenuItemClickListener; - + import net.micode.notes.R; - + +// 下拉菜单类,用于在按钮点击时显示一个弹出菜单 public class DropdownMenu { - private Button mButton; - private PopupMenu mPopupMenu; - private Menu mMenu; - + private Button mButton; // 用于触发下拉菜单的按钮 + private PopupMenu mPopupMenu; // 弹出菜单对象 + private Menu mMenu; // 菜单对象 + + // 构造函数,初始化下拉菜单,设置按钮背景,并将菜单资源加载到弹出菜单中 public DropdownMenu(Context context, Button button, int menuId) { mButton = button; mButton.setBackgroundResource(R.drawable.dropdown_icon); @@ -44,18 +46,21 @@ public class DropdownMenu { } }); } - + + // 设置下拉菜单项点击监听器 public void setOnDropdownMenuItemClickListener(OnMenuItemClickListener listener) { if (mPopupMenu != null) { mPopupMenu.setOnMenuItemClickListener(listener); } } - + + // 根据菜单项的ID查找菜单项 public MenuItem findItem(int id) { return mMenu.findItem(id); } - + + // 设置按钮的标题 public void setTitle(CharSequence title) { mButton.setText(title); } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/ui/FoldersListAdapter.java b/src/Notes-master/src/net/micode/notes/ui/FoldersListAdapter.java index 96b77da..1c6a78a 100644 --- a/src/Notes-master/src/net/micode/notes/ui/FoldersListAdapter.java +++ b/src/Notes-master/src/net/micode/notes/ui/FoldersListAdapter.java @@ -28,26 +28,31 @@ import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; - +// 自定义的 CursorAdapter 用于显示文件夹列表 public class FoldersListAdapter extends CursorAdapter { + // 定义查询文件夹时需要的列 public static final String [] PROJECTION = { NoteColumns.ID, NoteColumns.SNIPPET }; + // 列索引常量 public static final int ID_COLUMN = 0; public static final int NAME_COLUMN = 1; + // 构造函数,初始化 FoldersListAdapter public FoldersListAdapter(Context context, Cursor c) { super(context, c); // TODO Auto-generated constructor stub } + // 创建一个新的视图项 @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { return new FolderListItem(context); } + // 绑定数据到视图项 @Override public void bindView(View view, Context context, Cursor cursor) { if (view instanceof FolderListItem) { @@ -57,24 +62,28 @@ public class FoldersListAdapter extends CursorAdapter { } } + // 根据位置获取文件夹名称 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; + // 构造函数,初始化 FolderListItem 视图 public FolderListItem(Context context) { super(context); inflate(context, R.layout.folder_list_item, this); mName = (TextView) findViewById(R.id.tv_folder_name); } + // 绑定文件夹名称到视图 public void bind(String name) { mName.setText(name); } } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/ui/NoteEditActivity.java b/src/Notes-master/src/net/micode/notes/ui/NoteEditActivity.java index 96a9ff8..3e45406 100644 --- a/src/Notes-master/src/net/micode/notes/ui/NoteEditActivity.java +++ b/src/Notes-master/src/net/micode/notes/ui/NoteEditActivity.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.ui; - + import android.app.Activity; import android.app.AlarmManager; import android.app.AlertDialog; @@ -51,7 +51,7 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; - + import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.TextNote; @@ -64,26 +64,28 @@ 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_4x; - + import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; - - + +// 笔记编辑界面的Activity类 public class NoteEditActivity extends Activity implements OnClickListener, NoteSettingChangedListener, OnTextViewChangeListener { + // 用于存储笔记头部视图的ViewHolder类 private class HeadViewHolder { public TextView tvModified; - + public ImageView ivAlertIcon; - + public TextView tvAlertDate; - + public ImageView ibSetBgColor; } - + + // 背景色选择按钮和颜色ID的映射 private static final Map sBgSelectorBtnsMap = new HashMap(); static { sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW); @@ -92,7 +94,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, sBgSelectorBtnsMap.put(R.id.iv_bg_green, ResourceParser.GREEN); sBgSelectorBtnsMap.put(R.id.iv_bg_white, ResourceParser.WHITE); } - + + // 背景色选择后的显示标记和颜色ID的映射 private static final Map sBgSelectorSelectionMap = new HashMap(); static { sBgSelectorSelectionMap.put(ResourceParser.YELLOW, R.id.iv_bg_yellow_select); @@ -101,7 +104,8 @@ 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); } - + + // 字体大小选择按钮和字体大小ID的映射 private static final Map sFontSizeBtnsMap = new HashMap(); static { sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE); @@ -109,7 +113,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, sFontSizeBtnsMap.put(R.id.ll_font_normal, ResourceParser.TEXT_MEDIUM); sFontSizeBtnsMap.put(R.id.ll_font_super, ResourceParser.TEXT_SUPER); } - + + // 字体大小选择后的显示标记和字体大小ID的映射 private static final Map sFontSelectorSelectionMap = new HashMap(); static { sFontSelectorSelectionMap.put(ResourceParser.TEXT_LARGE, R.id.iv_large_select); @@ -117,54 +122,52 @@ 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); } - + private static final String TAG = "NoteEditActivity"; - + private HeadViewHolder mNoteHeaderHolder; - + private View mHeadViewPanel; - + private View mNoteBgColorSelector; - + private View mFontSizeSelector; - + private EditText mNoteEditor; - + private View mNoteEditorPanel; - + private WorkingNote mWorkingNote; - + private SharedPreferences mSharedPrefs; private int mFontSizeId; - + private static final String PREFERENCE_FONT_SIZE = "pref_font_size"; - + private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10; - + public static final String TAG_CHECKED = String.valueOf('\u221A'); public static final String TAG_UNCHECKED = String.valueOf('\u25A1'); - + private LinearLayout mEditTextList; - + private String mUserQuery; private Pattern mPattern; - + + // 初始化Activity视图 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.note_edit); - + if (savedInstanceState == null && !initActivityState(getIntent())) { finish(); return; } initResources(); } - - /** - * Current activity may be killed when the memory is low. Once it is killed, for another time - * user load this activity, we should restore the former state - */ + + // 当Activity被系统杀死后,恢复其状态 @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); @@ -178,25 +181,19 @@ public class NoteEditActivity extends Activity implements OnClickListener, Log.d(TAG, "Restoring from killed activity"); } } - + + // 初始化Activity状态,根据Intent决定加载笔记或创建新笔记 private boolean initActivityState(Intent intent) { - /** - * If the user specified the {@link Intent#ACTION_VIEW} but not provided with id, - * then jump to the NotesListActivity - */ mWorkingNote = null; if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) { long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0); mUserQuery = ""; - - /** - * Starting from the searched result - */ + if (intent.hasExtra(SearchManager.EXTRA_DATA_KEY)) { noteId = Long.parseLong(intent.getStringExtra(SearchManager.EXTRA_DATA_KEY)); mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY); } - + if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) { Intent jump = new Intent(this, NotesListActivity.class); startActivity(jump); @@ -215,7 +212,6 @@ public class NoteEditActivity extends Activity implements OnClickListener, 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 long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0); int widgetId = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); @@ -223,8 +219,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, Notes.TYPE_WIDGET_INVALIDE); int bgResId = intent.getIntExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, ResourceParser.getDefaultBgId(this)); - - // Parse call-record note + String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); long callDate = intent.getLongExtra(Notes.INTENT_EXTRA_CALL_DATE, 0); if (callDate != 0 && phoneNumber != null) { @@ -249,7 +244,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId, widgetType, bgResId); } - + getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); @@ -261,13 +256,15 @@ public class NoteEditActivity extends Activity implements OnClickListener, mWorkingNote.setOnSettingStatusChangedListener(this); return true; } - + + // Activity恢复时初始化笔记显示 @Override protected void onResume() { super.onResume(); initNoteScreen(); } - + + // 初始化笔记显示界面,包括背景颜色、字体大小、修改日期等 private void initNoteScreen() { mNoteEditor.setTextAppearance(this, TextAppearanceResources .getTexAppearanceResource(mFontSizeId)); @@ -282,19 +279,16 @@ public class NoteEditActivity extends Activity implements OnClickListener, } 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 | DateUtils.FORMAT_SHOW_YEAR)); - - /** - * TODO: Add the menu for setting alert. Currently disable it because the DateTimePicker - * is not ready - */ + showAlertHeader(); } - + + // 显示或隐藏提醒头部信息 private void showAlertHeader() { if (mWorkingNote.hasClockAlert()) { long time = System.currentTimeMillis(); @@ -311,28 +305,26 @@ public class NoteEditActivity extends Activity implements OnClickListener, mNoteHeaderHolder.ivAlertIcon.setVisibility(View.GONE); }; } - + + // 处理新的Intent,可能需要重新加载笔记或创建新笔记 @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); initActivityState(intent); } - + + // 保存Activity状态,在系统需要恢复Activity时使用 @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 - */ if (!mWorkingNote.existInDatabase()) { saveNote(); } outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId()); Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState"); } - + + // 处理触摸事件,用于隐藏颜色和字体大小选择面板 @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (mNoteBgColorSelector.getVisibility() == View.VISIBLE @@ -340,7 +332,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, mNoteBgColorSelector.setVisibility(View.GONE); return true; } - + if (mFontSizeSelector.getVisibility() == View.VISIBLE && !inRangeOfView(mFontSizeSelector, ev)) { mFontSizeSelector.setVisibility(View.GONE); @@ -348,7 +340,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return super.dispatchTouchEvent(ev); } - + + // 判断触摸事件是否发生在指定视图内 private boolean inRangeOfView(View view, MotionEvent ev) { int []location = new int[2]; view.getLocationOnScreen(location); @@ -362,7 +355,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return true; } - + + // 初始化视图资源 private void initResources() { mHeadViewPanel = findViewById(R.id.note_title); mNoteHeaderHolder = new HeadViewHolder(); @@ -378,7 +372,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, ImageView iv = (ImageView) findViewById(id); iv.setOnClickListener(this); } - + mFontSizeSelector = findViewById(R.id.font_size_selector); for (int id : sFontSizeBtnsMap.keySet()) { View view = findViewById(id); @@ -386,17 +380,13 @@ 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} - */ if(mFontSizeId >= TextAppearanceResources.getResourcesSize()) { mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE; } mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list); } - + + // 暂停Activity时保存笔记并清理设置状态 @Override protected void onPause() { super.onPause(); @@ -405,7 +395,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, } clearSettingState(); } - + + // 更新桌面小部件显示 private void updateWidget() { Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) { @@ -416,21 +407,22 @@ public class NoteEditActivity extends Activity implements OnClickListener, Log.e(TAG, "Unspported widget type"); return; } - + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { mWorkingNote.getWidgetId() }); - + sendBroadcast(intent); setResult(RESULT_OK, intent); } - + + // 处理视图点击事件,包括颜色和字体大小选择 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); @@ -451,17 +443,19 @@ public class NoteEditActivity extends Activity implements OnClickListener, mFontSizeSelector.setVisibility(View.GONE); } } - + + // 处理返回键事件,如果设置面板可见则隐藏,否则保存笔记后返回 @Override public void onBackPressed() { if(clearSettingState()) { return; } - + saveNote(); super.onBackPressed(); } - + + // 清理设置面板状态 private boolean clearSettingState() { if (mNoteBgColorSelector.getVisibility() == View.VISIBLE) { mNoteBgColorSelector.setVisibility(View.GONE); @@ -472,14 +466,16 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return false; } - + + // 处理笔记背景颜色变化事件 public void onBackgroundColorChanged() { findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( View.VISIBLE); mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId()); mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId()); } - + + // 准备选项菜单,根据笔记状态动态更新菜单项 @Override public boolean onPrepareOptionsMenu(Menu menu) { if (isFinishing()) { @@ -504,7 +500,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return true; } - + + // 处理选项菜单项点击事件 @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { @@ -552,7 +549,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return true; } - + + // 设置提醒时间 private void setReminder() { DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis()); d.setOnDateTimeSetListener(new OnDateTimeSetListener() { @@ -562,30 +560,27 @@ public class NoteEditActivity extends Activity implements OnClickListener, }); d.show(); } - - /** - * Share note to apps that support {@link Intent#ACTION_SEND} action - * and {@text/plain} type - */ + + // 分享笔记内容到支持ACTION_SEND的其他应用 private void sendTo(Context context, String info) { Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_TEXT, info); intent.setType("text/plain"); context.startActivity(intent); } - + + // 创建新笔记,跳转到新笔记编辑界面 private void createNewNote() { - // Firstly, save current editing notes saveNote(); - - // For safety, start a new NoteEditActivity + finish(); Intent intent = new Intent(this, NoteEditActivity.class); intent.setAction(Intent.ACTION_INSERT_OR_EDIT); intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mWorkingNote.getFolderId()); startActivity(intent); } - + + // 删除当前笔记 private void deleteCurrentNote() { if (mWorkingNote.existInDatabase()) { HashSet ids = new HashSet(); @@ -607,16 +602,14 @@ public class NoteEditActivity extends Activity implements OnClickListener, } mWorkingNote.markDeleted(true); } - + + // 判断是否处于同步模式 private boolean isSyncMode() { return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0; } - + + // 处理时钟提醒变化事件,设置或取消提醒 public void onClockAlertChanged(long date, boolean set) { - /** - * User could set clock to an unsaved note, so before setting the - * alert clock, we should save the note first - */ if (!mWorkingNote.existInDatabase()) { saveNote(); } @@ -632,31 +625,28 @@ public class NoteEditActivity extends Activity implements OnClickListener, alarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent); } } else { - /** - * There is the condition that user has input nothing (the note is - * not worthy saving), we have no note id, remind the user that he - * should input something - */ Log.e(TAG, "Clock alert setting error"); showToast(R.string.error_note_empty_for_clock); } } - + + // 处理小部件变化事件,更新小部件显示 public void onWidgetChanged() { updateWidget(); } - + + // 处理EditText删除事件,调整列表项索引 public void onEditTextDelete(int index, String text) { int childCount = mEditTextList.getChildCount(); if (childCount == 1) { return; } - + for (int i = index + 1; i < childCount; i++) { ((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text)) .setIndex(i - 1); } - + mEditTextList.removeViewAt(index); NoteEditText edit = null; if(index == 0) { @@ -671,15 +661,13 @@ public class NoteEditActivity extends Activity implements OnClickListener, edit.requestFocus(); edit.setSelection(length); } - + + // 处理EditText输入事件,添加新列表项 public void onEditTextEnter(int index, String text) { - /** - * Should not happen, check for debug - */ if(index > mEditTextList.getChildCount()) { Log.e(TAG, "Index out of mEditTextList boundrary, should not happen"); } - + View view = getListItem(text, index); mEditTextList.addView(view, index); NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text); @@ -690,7 +678,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, .setIndex(i); } } - + + // 切换到列表模式,根据笔记内容生成列表项 private void switchToListMode(String text) { mEditTextList.removeAllViews(); String[] items = text.split("\n"); @@ -703,11 +692,12 @@ public class NoteEditActivity extends Activity implements OnClickListener, } mEditTextList.addView(getListItem("", index)); mEditTextList.getChildAt(index).findViewById(R.id.et_edit_text).requestFocus(); - + mNoteEditor.setVisibility(View.GONE); mEditTextList.setVisibility(View.VISIBLE); } - + + // 获取高亮查询结果,用于显示搜索关键词 private Spannable getHighlightQueryResult(String fullText, String userQuery) { SpannableString spannable = new SpannableString(fullText == null ? "" : fullText); if (!TextUtils.isEmpty(userQuery)) { @@ -724,7 +714,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return spannable; } - + + // 生成一个新的列表项视图 private View getListItem(String item, int index) { View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null); final NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text); @@ -739,7 +730,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, } } }); - + if (item.startsWith(TAG_CHECKED)) { cb.setChecked(true); edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); @@ -749,13 +740,14 @@ public class NoteEditActivity extends Activity implements OnClickListener, edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG); item = item.substring(TAG_UNCHECKED.length(), item.length()).trim(); } - + edit.setOnTextViewChangeListener(this); edit.setIndex(index); edit.setText(getHighlightQueryResult(item, mUserQuery)); return view; } - + + // 处理EditText文本变化事件,显示或隐藏复选框 public void onTextChange(int index, boolean hasText) { if (index >= mEditTextList.getChildCount()) { Log.e(TAG, "Wrong index, should not happen"); @@ -767,7 +759,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.GONE); } } - + + // 处理笔记模式变化事件,从普通模式切换到列表模式或反之 public void onCheckListModeChanged(int oldMode, int newMode) { if (newMode == TextNote.MODE_CHECK_LIST) { switchToListMode(mNoteEditor.getText().toString()); @@ -781,7 +774,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, mNoteEditor.setVisibility(View.VISIBLE); } } - + + // 获取正在编辑的文本内容,根据列表模式添加标签 private boolean getWorkingText() { boolean hasChecked = false; if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { @@ -804,33 +798,23 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return hasChecked; } - + + // 保存笔记内容到数据库 private boolean saveNote() { getWorkingText(); boolean saved = mWorkingNote.saveNote(); if (saved) { - /** - * There are two modes from List view to edit view, open one note, - * create/edit a node. Opening node requires to the original - * position in the list when back from edit view, while creating a - * new node requires to the top of the list. This code - * {@link #RESULT_OK} is used to identify the create/edit state - */ setResult(RESULT_OK); } return saved; } - + + // 将笔记快捷方式添加到桌面 private void sendToDesktop() { - /** - * Before send message to home, we should make sure that current - * editing note is exists in databases. So, for new note, firstly - * save it - */ if (!mWorkingNote.existInDatabase()) { saveNote(); } - + if (mWorkingNote.getNoteId() > 0) { Intent sender = new Intent(); Intent shortcutIntent = new Intent(this, NoteEditActivity.class); @@ -846,28 +830,26 @@ public class NoteEditActivity extends Activity implements OnClickListener, showToast(R.string.info_note_enter_desktop); sendBroadcast(sender); } else { - /** - * There is the condition that user has input nothing (the note is - * not worthy saving), we have no note id, remind the user that he - * should input something - */ Log.e(TAG, "Send to desktop error"); showToast(R.string.error_note_empty_for_send_to_desktop); } } - + + // 生成桌面快捷方式的标题,截取笔记内容的一部分作为标题 private String makeShortcutIconTitle(String content) { content = content.replace(TAG_CHECKED, ""); content = content.replace(TAG_UNCHECKED, ""); return content.length() > SHORTCUT_ICON_TITLE_MAX_LEN ? content.substring(0, SHORTCUT_ICON_TITLE_MAX_LEN) : content; } - + + // 显示短Toast消息 private void showToast(int resId) { showToast(resId, Toast.LENGTH_SHORT); } - + + // 显示指定持续时间的Toast消息 private void showToast(int resId, int duration) { Toast.makeText(this, resId, duration).show(); } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/ui/NoteEditText.java b/src/Notes-master/src/net/micode/notes/ui/NoteEditText.java index 2afe2a8..d350c57 100644 --- a/src/Notes-master/src/net/micode/notes/ui/NoteEditText.java +++ b/src/Notes-master/src/net/micode/notes/ui/NoteEditText.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.ui; - + import android.content.Context; import android.graphics.Rect; import android.text.Layout; @@ -31,28 +31,29 @@ import android.view.MenuItem; import android.view.MenuItem.OnMenuItemClickListener; import android.view.MotionEvent; import android.widget.EditText; - + import net.micode.notes.R; - + import java.util.HashMap; import java.util.Map; - + +// 自定义的EditText,用于笔记应用中,支持删除、添加文本事件监听 public class NoteEditText extends EditText { private static final String TAG = "NoteEditText"; private int mIndex; private int mSelectionStartBeforeDelete; - + private static final String SCHEME_TEL = "tel:" ; private static final String SCHEME_HTTP = "http:" ; private static final String SCHEME_EMAIL = "mailto:" ; - + private static final Map sSchemaActionResMap = new HashMap(); static { sSchemaActionResMap.put(SCHEME_TEL, R.string.note_link_tel); sSchemaActionResMap.put(SCHEME_HTTP, R.string.note_link_web); sSchemaActionResMap.put(SCHEME_EMAIL, R.string.note_link_email); } - + /** * Call by the {@link NoteEditActivity} to delete or add edit text */ @@ -62,65 +63,69 @@ public class NoteEditText extends EditText { * and the text is null */ void onEditTextDelete(int index, String text); - + /** * Add edit text after current edit text when {@link KeyEvent#KEYCODE_ENTER} * happen */ void onEditTextEnter(int index, String text); - + /** * Hide or show item option when text change */ void onTextChange(int index, boolean hasText); } - + private OnTextViewChangeListener mOnTextViewChangeListener; - + public NoteEditText(Context context) { super(context, null); mIndex = 0; } - + + // 设置当前文本框的索引 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); } - + public NoteEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub } - + + // 处理触摸事件,更新光标位置 @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: - + int x = (int) event.getX(); int y = (int) event.getY(); x -= getTotalPaddingLeft(); y -= getTotalPaddingTop(); x += getScrollX(); y += getScrollY(); - + Layout layout = getLayout(); int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); Selection.setSelection(getText(), off); break; } - + return super.onTouchEvent(event); } - + + // 处理按键按下事件,记录删除操作前的光标位置 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { @@ -137,7 +142,8 @@ public class NoteEditText extends EditText { } return super.onKeyDown(keyCode, event); } - + + // 处理按键弹起事件,根据按键类型执行相应操作 @Override public boolean onKeyUp(int keyCode, KeyEvent event) { switch(keyCode) { @@ -166,7 +172,8 @@ public class NoteEditText extends EditText { } return super.onKeyUp(keyCode, event); } - + + // 当EditText焦点发生变化时调用,通知监听器文本是否有内容 @Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { if (mOnTextViewChangeListener != null) { @@ -178,16 +185,17 @@ public class NoteEditText extends EditText { } super.onFocusChanged(focused, direction, previouslyFocusedRect); } - + + // 创建上下文菜单,处理URL点击事件 @Override protected void onCreateContextMenu(ContextMenu menu) { if (getText() instanceof Spanned) { int selStart = getSelectionStart(); int selEnd = getSelectionEnd(); - + int min = Math.min(selStart, selEnd); int max = Math.max(selStart, selEnd); - + final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class); if (urls.length == 1) { int defaultResId = 0; @@ -197,11 +205,11 @@ public class NoteEditText extends EditText { break; } } - + if (defaultResId == 0) { defaultResId = R.string.note_link_other; } - + menu.add(0, 0, 0, defaultResId).setOnMenuItemClickListener( new OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { @@ -214,4 +222,4 @@ public class NoteEditText extends EditText { } super.onCreateContextMenu(menu); } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/ui/NoteItemData.java b/src/Notes-master/src/net/micode/notes/ui/NoteItemData.java index 0f5a878..632fe29 100644 --- a/src/Notes-master/src/net/micode/notes/ui/NoteItemData.java +++ b/src/Notes-master/src/net/micode/notes/ui/NoteItemData.java @@ -13,19 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.ui; - + import android.content.Context; import android.database.Cursor; import android.text.TextUtils; - + import net.micode.notes.data.Contact; import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.tool.DataUtils; - - + +// 该类用于从数据库游标中提取笔记项数据,并处理与笔记位置相关的逻辑 public class NoteItemData { static final String [] PROJECTION = new String [] { NoteColumns.ID, @@ -41,7 +41,8 @@ public class NoteItemData { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE, }; - + + // 定义了游标中各个列的索引位置 private static final int ID_COLUMN = 0; private static final int ALERTED_DATE_COLUMN = 1; private static final int BG_COLOR_ID_COLUMN = 2; @@ -54,7 +55,8 @@ public class NoteItemData { private static final int TYPE_COLUMN = 9; private static final int WIDGET_ID_COLUMN = 10; private static final int WIDGET_TYPE_COLUMN = 11; - + + // 笔记项的各种属性 private long mId; private long mAlertDate; private int mBgColorId; @@ -69,13 +71,15 @@ public class NoteItemData { private int mWidgetType; private String mName; private String mPhoneNumber; - + + // 笔记项在列表中的位置信息 private boolean mIsLastItem; private boolean mIsFirstItem; private boolean mIsOnlyOneItem; private boolean mIsOneNoteFollowingFolder; private boolean mIsMultiNotesFollowingFolder; - + + // 构造函数,从游标中提取笔记项数据 public NoteItemData(Context context, Cursor cursor) { mId = cursor.getLong(ID_COLUMN); mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN); @@ -91,7 +95,7 @@ public class NoteItemData { mType = cursor.getInt(TYPE_COLUMN); mWidgetId = cursor.getInt(WIDGET_ID_COLUMN); mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN); - + mPhoneNumber = ""; if (mParentId == Notes.ID_CALL_RECORD_FOLDER) { mPhoneNumber = DataUtils.getCallNumberByNoteId(context.getContentResolver(), mId); @@ -102,20 +106,21 @@ public class NoteItemData { } } } - + if (mName == null) { mName = ""; } checkPostion(cursor); } - + + // 检查笔记项在列表中的位置信息 private void checkPostion(Cursor cursor) { mIsLastItem = cursor.isLast() ? true : false; mIsFirstItem = cursor.isFirst() ? true : false; mIsOnlyOneItem = (cursor.getCount() == 1); mIsMultiNotesFollowingFolder = false; mIsOneNoteFollowingFolder = false; - + if (mType == Notes.TYPE_NOTE && !mIsFirstItem) { int position = cursor.getPosition(); if (cursor.moveToPrevious()) { @@ -133,92 +138,114 @@ public class NoteItemData { } } } - + + // 判断该笔记项是否是单个笔记跟在一个文件夹后 public boolean isOneFollowingFolder() { return mIsOneNoteFollowingFolder; } - + + // 判断该笔记项是否是多个笔记跟在一个文件夹后 public boolean isMultiFollowingFolder() { return mIsMultiNotesFollowingFolder; } - + + // 判断该笔记项是否是列表中的最后一个项 public boolean isLast() { return mIsLastItem; } - + + // 获取与该笔记项关联的呼叫记录的联系人名称 public String getCallName() { return mName; } - + + // 判断该笔记项是否是列表中的第一个项 public boolean isFirst() { return mIsFirstItem; } - + + // 判断该笔记项是否是列表中唯一的项 public boolean isSingle() { return mIsOnlyOneItem; } - + + // 获取笔记项的ID public long getId() { return mId; } - + + // 获取笔记项的提醒日期 public long getAlertDate() { return mAlertDate; } - + + // 获取笔记项的创建日期 public long getCreatedDate() { return mCreatedDate; } - + + // 判断该笔记项是否有附件 public boolean hasAttachment() { return mHasAttachment; } - + + // 获取笔记项的修改日期 public long getModifiedDate() { return mModifiedDate; } - + + // 获取笔记项的背景颜色ID public int getBgColorId() { return mBgColorId; } - + + // 获取笔记项的父ID public long getParentId() { return mParentId; } - + + // 获取笔记项包含的笔记数量 public int getNotesCount() { return mNotesCount; } - + + // 获取笔记项所在的文件夹ID public long getFolderId () { return mParentId; } - + + // 获取笔记项的类型 public int getType() { return mType; } - + + // 获取笔记项的小部件类型 public int getWidgetType() { return mWidgetType; } - + + // 获取笔记项的小部件ID public int getWidgetId() { return mWidgetId; } - + + // 获取笔记项的摘要 public String getSnippet() { return mSnippet; } - + + // 判断该笔记项是否有提醒 public boolean hasAlert() { return (mAlertDate > 0); } - + + // 判断该笔记项是否是呼叫记录类型 public boolean isCallRecord() { return (mParentId == Notes.ID_CALL_RECORD_FOLDER && !TextUtils.isEmpty(mPhoneNumber)); } - + + // 静态方法,从游标中获取笔记项的类型 public static int getNoteType(Cursor cursor) { return cursor.getInt(TYPE_COLUMN); } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/ui/NotesListActivity.java b/src/Notes-master/src/net/micode/notes/ui/NotesListActivity.java index e843aec..5893567 100644 --- a/src/Notes-master/src/net/micode/notes/ui/NotesListActivity.java +++ b/src/Notes-master/src/net/micode/notes/ui/NotesListActivity.java @@ -126,12 +126,12 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt private NoteItemData mFocusNoteDataItem; private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=?"; - + private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" + " OR (" + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + NoteColumns.NOTES_COUNT + ">0)"; - + private final static int REQUEST_CODE_OPEN_NODE = 102; private final static int REQUEST_CODE_NEW_NODE = 103; @@ -951,4 +951,4 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt } return false; } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/ui/NotesListAdapter.java b/src/Notes-master/src/net/micode/notes/ui/NotesListAdapter.java index 51c9cb9..fc77697 100644 --- a/src/Notes-master/src/net/micode/notes/ui/NotesListAdapter.java +++ b/src/Notes-master/src/net/micode/notes/ui/NotesListAdapter.java @@ -13,48 +13,52 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.ui; - + import android.content.Context; import android.database.Cursor; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.CursorAdapter; - + import net.micode.notes.data.Notes; - + import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; - - + +// 自定义的CursorAdapter,用于显示笔记列表 public class NotesListAdapter extends CursorAdapter { private static final String TAG = "NotesListAdapter"; private Context mContext; private HashMap mSelectedIndex; private int mNotesCount; private boolean mChoiceMode; - + + // 用于存储小部件属性的内部类 public static class AppWidgetAttribute { public int widgetId; public int widgetType; }; - + + // 构造函数,初始化上下文和选择索引 public NotesListAdapter(Context context) { super(context, null); mSelectedIndex = new HashMap(); mContext = context; mNotesCount = 0; } - + + // 创建新的视图项 @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { return new NotesListItem(context); } - + + // 绑定数据到视图项 @Override public void bindView(View view, Context context, Cursor cursor) { if (view instanceof NotesListItem) { @@ -63,21 +67,25 @@ public class NotesListAdapter extends CursorAdapter { 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; } - + + // 全选或全不选所有笔记 public void selectAll(boolean checked) { Cursor cursor = getCursor(); for (int i = 0; i < getCount(); i++) { @@ -88,7 +96,8 @@ public class NotesListAdapter extends CursorAdapter { } } } - + + // 获取所有选中的笔记ID集合 public HashSet getSelectedItemIds() { HashSet itemSet = new HashSet(); for (Integer position : mSelectedIndex.keySet()) { @@ -101,10 +110,11 @@ public class NotesListAdapter extends CursorAdapter { } } } - + return itemSet; } - + + // 获取所有选中的小部件属性集合 public HashSet getSelectedWidget() { HashSet itemSet = new HashSet(); for (Integer position : mSelectedIndex.keySet()) { @@ -127,7 +137,8 @@ public class NotesListAdapter extends CursorAdapter { } return itemSet; } - + + // 获取选中的笔记数量 public int getSelectedCount() { Collection values = mSelectedIndex.values(); if (null == values) { @@ -142,31 +153,36 @@ 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(); } - + + // 更改Cursor时,更新笔记数量 @Override public void changeCursor(Cursor cursor) { super.changeCursor(cursor); calcNotesCount(); } - + + // 计算笔记数量 private void calcNotesCount() { mNotesCount = 0; for (int i = 0; i < getCount(); i++) { @@ -181,4 +197,4 @@ public class NotesListAdapter extends CursorAdapter { } } } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/ui/NotesListItem.java b/src/Notes-master/src/net/micode/notes/ui/NotesListItem.java index 1221e80..1546bbe 100644 --- a/src/Notes-master/src/net/micode/notes/ui/NotesListItem.java +++ b/src/Notes-master/src/net/micode/notes/ui/NotesListItem.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.ui; - + import android.content.Context; import android.text.format.DateUtils; import android.view.View; @@ -23,13 +23,13 @@ import android.widget.CheckBox; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; - + import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.tool.DataUtils; import net.micode.notes.tool.ResourceParser.NoteItemBgResources; - - + +// NotesListItem 类继承自 LinearLayout,用于表示笔记列表中的一个项 public class NotesListItem extends LinearLayout { private ImageView mAlert; private TextView mTitle; @@ -37,7 +37,8 @@ public class NotesListItem extends LinearLayout { private TextView mCallName; private NoteItemData mItemData; private CheckBox mCheckBox; - + + // 构造函数,初始化 NotesListItem 的视图组件 public NotesListItem(Context context) { super(context); inflate(context, R.layout.note_item, this); @@ -47,7 +48,8 @@ public class NotesListItem extends LinearLayout { mCallName = (TextView) findViewById(R.id.tv_name); mCheckBox = (CheckBox) findViewById(android.R.id.checkbox); } - + + // 绑定数据到 NotesListItem 的视图组件,并设置选择模式和选中状态 public void bind(Context context, NoteItemData data, boolean choiceMode, boolean checked) { if (choiceMode && data.getType() == Notes.TYPE_NOTE) { mCheckBox.setVisibility(View.VISIBLE); @@ -55,7 +57,7 @@ public class NotesListItem extends LinearLayout { } else { mCheckBox.setVisibility(View.GONE); } - + mItemData = data; if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { mCallName.setVisibility(View.GONE); @@ -78,7 +80,7 @@ public class NotesListItem extends LinearLayout { } else { mCallName.setVisibility(View.GONE); mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem); - + if (data.getType() == Notes.TYPE_FOLDER) { mTitle.setText(data.getSnippet() + context.getString(R.string.format_folder_files_count, @@ -95,10 +97,11 @@ public class NotesListItem extends LinearLayout { } } mTime.setText(DateUtils.getRelativeTimeSpanString(data.getModifiedDate())); - + setBackground(data); } - + + // 根据数据设置 NotesListItem 的背景资源 private void setBackground(NoteItemData data) { int id = data.getBgColorId(); if (data.getType() == Notes.TYPE_NOTE) { @@ -115,8 +118,9 @@ public class NotesListItem extends LinearLayout { setBackgroundResource(NoteItemBgResources.getFolderBgRes()); } } - + + // 获取绑定到此 NotesListItem 的数据 public NoteItemData getItemData() { return mItemData; } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/ui/NotesPreferenceActivity.java b/src/Notes-master/src/net/micode/notes/ui/NotesPreferenceActivity.java index 07c5f7e..48125be 100644 --- a/src/Notes-master/src/net/micode/notes/ui/NotesPreferenceActivity.java +++ b/src/Notes-master/src/net/micode/notes/ui/NotesPreferenceActivity.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.ui; - + import android.accounts.Account; import android.accounts.AccountManager; import android.app.ActionBar; @@ -41,59 +41,60 @@ import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; - + import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.gtask.remote.GTaskSyncService; - - + +// 设置界面活动类,继承自PreferenceActivity public class NotesPreferenceActivity extends PreferenceActivity { public static final String PREFERENCE_NAME = "notes_preferences"; - + public static final String PREFERENCE_SYNC_ACCOUNT_NAME = "pref_key_account_name"; - + public static final String PREFERENCE_LAST_SYNC_TIME = "pref_last_sync_time"; - + public static final String PREFERENCE_SET_BG_COLOR_KEY = "pref_key_bg_random_appear"; - + private static final String PREFERENCE_SYNC_ACCOUNT_KEY = "pref_sync_account_key"; - + private static final String AUTHORITIES_FILTER_KEY = "authorities"; - + private PreferenceCategory mAccountCategory; - + private GTaskReceiver mReceiver; - + private Account[] mOriAccounts; - + private boolean mHasAddedAccount; - + + // 创建活动时初始化界面 @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); - - /* using the app icon for navigation */ + + /* 使用应用图标进行导航 */ getActionBar().setDisplayHomeAsUpEnabled(true); - + addPreferencesFromResource(R.xml.preferences); mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY); mReceiver = new GTaskReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME); registerReceiver(mReceiver, filter); - + mOriAccounts = null; View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null); getListView().addHeaderView(header, null, true); } - + + // 恢复活动时刷新界面 @Override protected void onResume() { super.onResume(); - - // need to set sync account automatically if user has added a new - // account + + // 如果用户添加了新账户,自动设置同步账户 if (mHasAddedAccount) { Account[] accounts = getGoogleAccounts(); if (mOriAccounts != null && accounts.length > mOriAccounts.length) { @@ -112,10 +113,11 @@ public class NotesPreferenceActivity extends PreferenceActivity { } } } - + refreshUI(); } - + + // 销毁活动时注销广播接收器 @Override protected void onDestroy() { if (mReceiver != null) { @@ -123,10 +125,11 @@ public class NotesPreferenceActivity extends PreferenceActivity { } super.onDestroy(); } - + + // 加载账户偏好设置 private void loadAccountPreference() { mAccountCategory.removeAll(); - + Preference accountPref = new Preference(this); final String defaultAccount = getSyncAccountName(this); accountPref.setTitle(getString(R.string.preferences_account_title)); @@ -135,11 +138,10 @@ public class NotesPreferenceActivity extends PreferenceActivity { public boolean onPreferenceClick(Preference preference) { if (!GTaskSyncService.isSyncing()) { if (TextUtils.isEmpty(defaultAccount)) { - // the first time to set account + // 第一次设置账户 showSelectAccountAlertDialog(); } else { - // if the account has already been set, we need to promp - // user about the risk + // 如果账户已经设置,提示用户切换账户的风险 showChangeAccountConfirmAlertDialog(); } } else { @@ -150,15 +152,16 @@ public class NotesPreferenceActivity extends PreferenceActivity { return true; } }); - + mAccountCategory.addPreference(accountPref); } - + + // 加载同步按钮 private void loadSyncButton() { Button syncButton = (Button) findViewById(R.id.preference_sync_button); TextView lastSyncTimeView = (TextView) findViewById(R.id.prefenerece_sync_status_textview); - - // set button state + + // 设置按钮状态 if (GTaskSyncService.isSyncing()) { syncButton.setText(getString(R.string.preferences_button_sync_cancel)); syncButton.setOnClickListener(new View.OnClickListener() { @@ -175,8 +178,8 @@ public class NotesPreferenceActivity extends PreferenceActivity { }); } syncButton.setEnabled(!TextUtils.isEmpty(getSyncAccountName(this))); - - // set last sync time + + // 设置上次同步时间 if (GTaskSyncService.isSyncing()) { lastSyncTimeView.setText(GTaskSyncService.getProgressString()); lastSyncTimeView.setVisibility(View.VISIBLE); @@ -192,30 +195,32 @@ public class NotesPreferenceActivity extends PreferenceActivity { } } } - + + // 刷新用户界面 private void refreshUI() { loadAccountPreference(); loadSyncButton(); } - + + // 显示选择账户的对话框 private void showSelectAccountAlertDialog() { AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); - + View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null); TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title); titleTextView.setText(getString(R.string.preferences_dialog_select_account_title)); TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle); subtitleTextView.setText(getString(R.string.preferences_dialog_select_account_tips)); - + dialogBuilder.setCustomTitle(titleView); dialogBuilder.setPositiveButton(null, null); - + Account[] accounts = getGoogleAccounts(); String defAccount = getSyncAccountName(this); - + mOriAccounts = accounts; mHasAddedAccount = false; - + if (accounts.length > 0) { CharSequence[] items = new CharSequence[accounts.length]; final CharSequence[] itemMapping = items; @@ -236,10 +241,10 @@ public class NotesPreferenceActivity extends PreferenceActivity { } }); } - + View addAccountView = LayoutInflater.from(this).inflate(R.layout.add_account_text, null); dialogBuilder.setView(addAccountView); - + final AlertDialog dialog = dialogBuilder.show(); addAccountView.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { @@ -253,10 +258,11 @@ public class NotesPreferenceActivity extends PreferenceActivity { } }); } - + + // 显示更改账户确认对话框 private void showChangeAccountConfirmAlertDialog() { AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); - + View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null); TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title); titleTextView.setText(getString(R.string.preferences_dialog_change_account_title, @@ -264,7 +270,7 @@ public class NotesPreferenceActivity extends PreferenceActivity { TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle); subtitleTextView.setText(getString(R.string.preferences_dialog_change_account_warn_msg)); dialogBuilder.setCustomTitle(titleView); - + CharSequence[] menuItemArray = new CharSequence[] { getString(R.string.preferences_menu_change_account), getString(R.string.preferences_menu_remove_account), @@ -282,12 +288,14 @@ public class NotesPreferenceActivity extends PreferenceActivity { }); dialogBuilder.show(); } - + + // 获取Google账户列表 private Account[] getGoogleAccounts() { AccountManager accountManager = AccountManager.get(this); return accountManager.getAccountsByType("com.google"); } - + + // 设置同步账户 private void setSyncAccount(String account) { if (!getSyncAccountName(this).equals(account)) { SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); @@ -298,11 +306,11 @@ public class NotesPreferenceActivity extends PreferenceActivity { editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, ""); } editor.commit(); - - // clean up last sync time + + // 清除上次同步时间 setLastSyncTime(this, 0); - - // clean up local gtask related info + + // 清除本地Gtask相关信息 new Thread(new Runnable() { public void run() { ContentValues values = new ContentValues(); @@ -311,13 +319,14 @@ public class NotesPreferenceActivity extends PreferenceActivity { getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null); } }).start(); - + Toast.makeText(NotesPreferenceActivity.this, getString(R.string.preferences_toast_success_set_accout, account), Toast.LENGTH_SHORT).show(); } } - + + // 移除同步账户 private void removeSyncAccount() { SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = settings.edit(); @@ -328,8 +337,8 @@ public class NotesPreferenceActivity extends PreferenceActivity { editor.remove(PREFERENCE_LAST_SYNC_TIME); } editor.commit(); - - // clean up local gtask related info + + // 清除本地Gtask相关信息 new Thread(new Runnable() { public void run() { ContentValues values = new ContentValues(); @@ -339,13 +348,15 @@ public class NotesPreferenceActivity extends PreferenceActivity { } }).start(); } - + + // 获取同步账户名称 public static String getSyncAccountName(Context context) { SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, ""); } - + + // 设置上次同步时间 public static void setLastSyncTime(Context context, long time) { SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); @@ -353,15 +364,17 @@ public class NotesPreferenceActivity extends PreferenceActivity { editor.putLong(PREFERENCE_LAST_SYNC_TIME, time); editor.commit(); } - + + // 获取上次同步时间 public static long getLastSyncTime(Context context) { SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0); } - + + // 广播接收器,用于接收同步状态更新 private class GTaskReceiver extends BroadcastReceiver { - + @Override public void onReceive(Context context, Intent intent) { refreshUI(); @@ -370,10 +383,11 @@ public class NotesPreferenceActivity extends PreferenceActivity { syncStatus.setText(intent .getStringExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_PROGRESS_MSG)); } - + } } - + + // 选项菜单项点击事件处理 public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: @@ -385,4 +399,4 @@ public class NotesPreferenceActivity extends PreferenceActivity { return false; } } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider.java b/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider.java index ec6f819..0fbd347 100644 --- a/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider.java +++ b/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.widget; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; @@ -24,27 +24,32 @@ import android.content.Intent; import android.database.Cursor; import android.util.Log; import android.widget.RemoteViews; - + import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.tool.ResourceParser; import net.micode.notes.ui.NoteEditActivity; import net.micode.notes.ui.NotesListActivity; - + +// 提供笔记小部件功能的抽象类,继承自AppWidgetProvider public abstract class NoteWidgetProvider extends AppWidgetProvider { + // 查询笔记时使用的投影列 public static final String [] PROJECTION = new String [] { NoteColumns.ID, NoteColumns.BG_COLOR_ID, NoteColumns.SNIPPET }; - + + // 投影列对应的索引 public static final int COLUMN_ID = 0; public static final int COLUMN_BG_COLOR_ID = 1; public static final int COLUMN_SNIPPET = 2; - + + // 日志标签 private static final String TAG = "NoteWidgetProvider"; - + + // 当小部件被删除时调用,更新数据库中的小部件ID为无效值 @Override public void onDeleted(Context context, int[] appWidgetIds) { ContentValues values = new ContentValues(); @@ -56,7 +61,8 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { new String[] { String.valueOf(appWidgetIds[i])}); } } - + + // 根据小部件ID获取笔记信息 private Cursor getNoteWidgetInfo(Context context, int widgetId) { return context.getContentResolver().query(Notes.CONTENT_NOTE_URI, PROJECTION, @@ -64,11 +70,13 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { new String[] { String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLER) }, null); } - + + // 更新小部件视图 protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { update(context, appWidgetManager, appWidgetIds, false); } - + + // 更新小部件视图,支持隐私模式 private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, boolean privacyMode) { for (int i = 0; i < appWidgetIds.length; i++) { @@ -79,7 +87,7 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]); intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType()); - + Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]); if (c != null && c.moveToFirst()) { if (c.getCount() > 1) { @@ -95,11 +103,11 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { snippet = context.getResources().getString(R.string.widget_havenot_content); intent.setAction(Intent.ACTION_INSERT_OR_EDIT); } - + if (c != null) { c.close(); } - + RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId()); rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId)); intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId); @@ -117,16 +125,19 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent, PendingIntent.FLAG_UPDATE_CURRENT); } - + rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent); appWidgetManager.updateAppWidget(appWidgetIds[i], rv); } } } - + + // 获取背景资源ID的方法,由子类实现 protected abstract int getBgResourceId(int bgId); - + + // 获取布局ID的方法,由子类实现 protected abstract int getLayoutId(); - + + // 获取小部件类型的ID,由子类实现 protected abstract int getWidgetType(); -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_2x.java b/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_2x.java index adcb2f7..ffc1401 100644 --- a/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_2x.java +++ b/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_2x.java @@ -13,35 +13,39 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package net.micode.notes.widget; - + import android.appwidget.AppWidgetManager; import android.content.Context; - + import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.tool.ResourceParser; - - + +// 2x2 小部件提供者类,继承自 NoteWidgetProvider public class NoteWidgetProvider_2x extends NoteWidgetProvider { + // 更新小部件时调用的方法 @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.update(context, appWidgetManager, appWidgetIds); } - + + // 返回 2x2 小部件的布局 ID @Override protected int getLayoutId() { return R.layout.widget_2x; } - + + // 根据背景 ID 返回对应的 2x2 小部件背景资源 ID @Override protected int getBgResourceId(int bgId) { return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId); } - + + // 返回 2x2 小部件的类型 ID @Override protected int getWidgetType() { return Notes.TYPE_WIDGET_2X; } -} +} \ No newline at end of file diff --git a/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_4x.java b/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_4x.java index c12a02e..d1b1240 100644 --- a/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_4x.java +++ b/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_4x.java @@ -1,19 +1,3 @@ -/* - * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package net.micode.notes.widget; import android.appwidget.AppWidgetManager; @@ -23,24 +7,28 @@ import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.tool.ResourceParser; - +// 定义一个4x4小部件的提供者类,继承自NoteWidgetProvider public class NoteWidgetProvider_4x extends NoteWidgetProvider { + // 覆盖父类的onUpdate方法,用于更新小部件的视图 @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.update(context, appWidgetManager, appWidgetIds); } + // 返回4x4小部件的布局资源ID protected int getLayoutId() { return R.layout.widget_4x; } + // 根据背景ID返回4x4小部件的背景资源ID @Override protected int getBgResourceId(int bgId) { return ResourceParser.WidgetBgResources.getWidget4xBgResource(bgId); } + // 返回小部件的类型,这里是4x4类型 @Override protected int getWidgetType() { return Notes.TYPE_WIDGET_4X; } -} +} \ No newline at end of file