From f7b3c00a10285e3165ef98f2b58c0e869c8b7c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=B6=A6=E6=B3=BD?= <3254719436@qq.com> Date: Thu, 18 Jan 2024 21:09:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E8=83=8C=E6=99=AF?= =?UTF-8?q?=E5=88=87=E6=8D=A2=EF=BC=8C=E6=AC=A2=E8=BF=8E=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=20drawable-hdpi=20menu=E5=8C=85=E4=B8=AD=E7=9A=84note=5Flist.x?= =?UTF-8?q?ml=20strings.xml=20layout\note=5Flist.xml=20NoteListActivity.ja?= =?UTF-8?q?va=20androidmanifest.xml=20ui\SplashActivity.java=20activity=5F?= =?UTF-8?q?splash.xml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/AndroidManifest.xml | 78 +-- .../java/net/micode/notes/data/Contact.java | 46 +- .../java/net/micode/notes/data/Notes.java | 16 +- .../notes/data/NotesDatabaseHelper.java | 20 +- .../net/micode/notes/data/NotesProvider.java | 13 +- .../net/micode/notes/gtask/data/MetaData.java | 14 +- .../net/micode/notes/gtask/data/Node.java | 11 +- .../net/micode/notes/gtask/data/SqlData.java | 24 +- .../net/micode/notes/gtask/data/SqlNote.java | 26 +- .../net/micode/notes/gtask/data/Task.java | 28 +- .../net/micode/notes/gtask/data/TaskList.java | 34 +- .../exception/ActionFailureException.java | 20 +- .../exception/NetworkFailureException.java | 26 +- .../notes/gtask/remote/GTaskASyncTask.java | 87 +-- .../java/net/micode/notes/model/Note.java | 139 ++-- .../net/micode/notes/model/WorkingNote.java | 140 ++-- .../net/micode/notes/ui/NoteEditActivity.java | 659 ++++-------------- .../net/micode/notes/ui/NoteEditText.java | 117 +--- src/main/res/layout/note_edit.xml | 9 - src/main/res/menu/sub_folder.xml | 7 - src/main/res/values-zh-rCN/strings.xml | 2 - src/main/res/values/colors.xml | 5 + src/main/res/values/styles.xml | 17 +- 23 files changed, 443 insertions(+), 1095 deletions(-) diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index e5c7d47..d805cd2 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -1,26 +1,10 @@ - - - + android:versionName="0.1"> - + @@ -34,44 +18,51 @@ + android:label="@string/app_name"> + android:windowSoftInputMode="adjustPan"> + + + - - + android:theme="@style/NoteTheme"> + + - + + - + @@ -81,13 +72,13 @@ + android:label="@string/app_widget2x2"> @@ -100,8 +91,7 @@ - + android:label="@string/app_widget4x4"> @@ -112,39 +102,33 @@ android:name="android.appwidget.provider" android:resource="@xml/widget_4x_info" /> - - + - - + android:name=".ui.AlarmReceiver" + android:process=":remote"> - - + android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar"> - + android:theme="@android:style/Theme.Holo.Light"> - + android:name=".gtask.remote.GTaskSyncService" + android:exported="false"> - + + \ No newline at end of file diff --git a/src/main/java/net/micode/notes/data/Contact.java b/src/main/java/net/micode/notes/data/Contact.java index b42deca..d97ac5d 100644 --- a/src/main/java/net/micode/notes/data/Contact.java +++ b/src/main/java/net/micode/notes/data/Contact.java @@ -22,57 +22,42 @@ import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.Data; import android.telephony.PhoneNumberUtils; import android.util.Log; + import java.util.HashMap; -// 该代码是一个名为Contact的类,用于获取联系人信息。 -//代码中定义了一个静态的HashMap变量sContactCache,用于缓存联系人信息。sContactCache的键是电话号码,值是联系人姓名。 -//定义了一个字符串常量CALLER_ID_SELECTION,用于查询联系人信息的条件。该条件是通过拼接字符串而得到的,包含了查询电话号码相等、数据类型为电话号码、联系人ID在指定范围内等条件。 -//代码中定义了一个静态方法getContact,用于根据电话号码获取联系人姓名。 public class Contact { - private static HashMap sContactCache; // 缓存联系人信息 - private static final String TAG = "Contact";//标签 - private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER - + ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'" - + " AND " + Data.RAW_CONTACT_ID + " IN " + private static HashMap sContactCache; + private static final String TAG = "Contact"; + + private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER + + ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'" + + " AND " + Data.RAW_CONTACT_ID + " IN " + "(SELECT raw_contact_id " + " FROM phone_lookup" - + " WHERE min_match = '+')"; // 查询联系人信息的条件 + + " WHERE min_match = '+')"; - /** - * 根据电话号码获取联系人姓名 - * @param context 上下文对象 - * @param phoneNumber 电话号码 - * @return 联系人姓名,如果未找到则返回null - */ -// 该方法首先检查缓存中是否已有该电话号码对应的联系人姓名,如果有则返回缓存中的值。如果缓存中没有该电话号码对应的联系人姓名,则通过查询数据库来获取联系人姓名。 -// 查询数据库的条件是根据电话号码生成的CALLER_ID_SELECTION。如果查询结果不为空且移动到第一条记录,则从结果中提取联系人姓名,并将其存入缓存中。如果查询结果为空,则返回null。 public static String getContact(Context context, String phoneNumber) { - if (sContactCache == null) { + if(sContactCache == null) { sContactCache = new HashMap(); } - // 查找HashMap中是否已有phoneNumber信息 - if (sContactCache.containsKey(phoneNumber)) { - return sContactCache.get(phoneNumber);//直接根据键值(电话号码)找到姓名 + if(sContactCache.containsKey(phoneNumber)) { + return sContactCache.get(phoneNumber); } String selection = CALLER_ID_SELECTION.replace("+", - PhoneNumberUtils.toCallerIDMinMatch(phoneNumber));//最小匹配原则查找电话号码 - - // 查找数据库中phoneNumber的信息 + PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)); Cursor cursor = context.getContentResolver().query( Data.CONTENT_URI, - new String[] { Phone.DISPLAY_NAME }, + new String [] { Phone.DISPLAY_NAME }, selection, new String[] { phoneNumber }, null); - // 判定查询结果 if (cursor != null && cursor.moveToFirst()) { try { - // 找到相关信息 String name = cursor.getString(0); - sContactCache.put(phoneNumber, name);//放入缓存块 + sContactCache.put(phoneNumber, name); return name; } catch (IndexOutOfBoundsException e) { Log.e(TAG, " Cursor get string error " + e.toString()); @@ -81,8 +66,7 @@ public class Contact { cursor.close(); } } else { - // 未找到相关信息 - Log.d(TAG, "No contact matched with number:" + phoneNumber);//给出反馈信息 + Log.d(TAG, "No contact matched with number:" + phoneNumber); return null; } } diff --git a/src/main/java/net/micode/notes/data/Notes.java b/src/main/java/net/micode/notes/data/Notes.java index fddf75c..f240604 100644 --- a/src/main/java/net/micode/notes/data/Notes.java +++ b/src/main/java/net/micode/notes/data/Notes.java @@ -17,7 +17,7 @@ package net.micode.notes.data; import android.net.Uri; -public class Notes {//定义Nodes类,初始化参数,都赋值成静态量 +public class Notes { public static final String AUTHORITY = "micode_notes"; public static final String TAG = "Notes"; public static final int TYPE_NOTE = 0; @@ -54,14 +54,14 @@ public class Notes {//定义Nodes类,初始化参数,都赋值成静态量 /** * Uri to query all notes and folders */ - public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note");//指定笔记的路径 + public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note"); /** * Uri to query data */ - public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data");//用于指定数据的路径,类似上面 + public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data"); - public interface NoteColumns {//定义笔记集ID、父集ID、创建日期,修改日期等等列名称以及类型,做初始化 + public interface NoteColumns { /** * The unique ID for a row *

Type: INTEGER (long)

@@ -167,7 +167,7 @@ public class Notes {//定义Nodes类,初始化参数,都赋值成静态量 public static final String VERSION = "version"; } - public interface DataColumns {//定义接口,给每行数据ID,类型,所属笔记集ID,内容数据等等做定义 + public interface DataColumns { /** * The unique ID for a row *

Type: INTEGER (long)

@@ -241,20 +241,20 @@ public class Notes {//定义Nodes类,初始化参数,都赋值成静态量 public static final String DATA5 = "data5"; } - public static final class TextNote implements DataColumns {//实现DataColumn接口,为数据库查询操作提供数据列名称 + public static final class TextNote implements DataColumns { /** * Mode to indicate the text in check list mode or not *

Type: Integer 1:check list mode 0: normal mode

*/ public static final String MODE = DATA1; - public static final int MODE_CHECK_LIST = 1;//表示当前文本是否还处于检查列清单的模式 + public static final int MODE_CHECK_LIST = 1; public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note"; public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note"; - public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note");//指定路径 + public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note"); } public static final class CallNote implements DataColumns { diff --git a/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java b/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java index 042c2d9..ffe5d57 100644 --- a/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java +++ b/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java @@ -27,7 +27,7 @@ import net.micode.notes.data.Notes.DataConstants; import net.micode.notes.data.Notes.NoteColumns; -public class NotesDatabaseHelper extends SQLiteOpenHelper { //定义数据库相关的名称以及标签 +public class NotesDatabaseHelper extends SQLiteOpenHelper { private static final String DB_NAME = "note.db"; private static final int DB_VERSION = 4; @@ -42,7 +42,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //定义数据库相 private static NotesDatabaseHelper mInstance; - private static final String CREATE_NOTE_TABLE_SQL =//规范定义数据库存储信息的格式以及组成部分 + private static final String CREATE_NOTE_TABLE_SQL = "CREATE TABLE " + TABLE.NOTE + "(" + NoteColumns.ID + " INTEGER PRIMARY KEY," + NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + @@ -85,7 +85,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //定义数据库相 /** * Increase folder's note count when move note to the folder */ - private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =//设置触发器,在笔记集更新的时候增加数量1 + private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = "CREATE TRIGGER increase_folder_count_on_update "+ " AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE + " BEGIN " + @@ -97,7 +97,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //定义数据库相 /** * Decrease folder's note count when move note from folder */ - private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =//类似的设置触发器,在笔记集更新的时候减少数量1 + private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = "CREATE TRIGGER decrease_folder_count_on_update " + " AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE + " BEGIN " + @@ -110,7 +110,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //定义数据库相 /** * Increase folder's note count when insert new note to the folder */ - private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER =//设置触发器,在笔记集创建的时候增加数量1 + private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER = "CREATE TRIGGER increase_folder_count_on_insert " + " AFTER INSERT ON " + TABLE.NOTE + " BEGIN " + @@ -122,7 +122,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //定义数据库相 /** * Decrease folder's note count when delete note from the folder */ - private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =//设置触发器,在笔记集删除文件的时候-1 + private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER = "CREATE TRIGGER decrease_folder_count_on_delete " + " AFTER DELETE ON " + TABLE.NOTE + " BEGIN " + @@ -135,7 +135,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //定义数据库相 /** * Update note's content when insert data with type {@link DataConstants#NOTE} */ - private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER =//设置触发器用于在笔记中数据更改时进行相应ID,字段等的更新 + private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER = "CREATE TRIGGER update_note_content_on_insert " + " AFTER INSERT ON " + TABLE.DATA + " WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" + @@ -210,14 +210,14 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //定义数据库相 super(context, DB_NAME, null, DB_VERSION); } - public void createNoteTable(SQLiteDatabase db) {//创建并管理日志信息表 + public void createNoteTable(SQLiteDatabase db) { db.execSQL(CREATE_NOTE_TABLE_SQL); reCreateNoteTableTriggers(db); createSystemFolder(db); Log.d(TAG, "note table has been created"); } - private void reCreateNoteTableTriggers(SQLiteDatabase db) {//重置触发器 + private void reCreateNoteTableTriggers(SQLiteDatabase db) { db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update"); db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update"); db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_delete"); @@ -301,7 +301,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //定义数据库相 } @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {//用于检查并进行数据库版本的更新,保障版本控制 + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { boolean reCreateTriggers = false; boolean skipV2 = false; diff --git a/src/main/java/net/micode/notes/data/NotesProvider.java b/src/main/java/net/micode/notes/data/NotesProvider.java index b29c6fd..edb0a60 100644 --- a/src/main/java/net/micode/notes/data/NotesProvider.java +++ b/src/main/java/net/micode/notes/data/NotesProvider.java @@ -35,7 +35,7 @@ import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.NotesDatabaseHelper.TABLE; -public class NotesProvider extends ContentProvider {//定义URL以及匹配规则 +public class NotesProvider extends ContentProvider { private static final UriMatcher mMatcher; private NotesDatabaseHelper mHelper; @@ -86,12 +86,12 @@ public class NotesProvider extends ContentProvider {//定义URL以及匹配规 } @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,//执行数据库查询操作 + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Cursor c = null; SQLiteDatabase db = mHelper.getReadableDatabase(); String id = null; - switch (mMatcher.match(uri)) {//匹配数据库查询关键字 + switch (mMatcher.match(uri)) { case URI_NOTE: c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null, sortOrder); @@ -148,7 +148,7 @@ public class NotesProvider extends ContentProvider {//定义URL以及匹配规 } @Override - public Uri insert(Uri uri, ContentValues values) {//insert向数据库中插入一条数据信息值 + public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = mHelper.getWritableDatabase(); long dataId = 0, noteId = 0, insertedId = 0; switch (mMatcher.match(uri)) { @@ -182,8 +182,7 @@ public class NotesProvider extends ContentProvider {//定义URL以及匹配规 } @Override - public int delete(Uri uri, String selection, String[] selectionArgs) {//实现删除操作 - /*这两个参数通常在一起使用,以定义一个特定的删除操作。selection 定义了哪些数据应该被删除,而 selectionArgs 为 selection 中的占位符提供了具体的值。*/ + public int delete(Uri uri, String selection, String[] selectionArgs) { int count = 0; String id = null; SQLiteDatabase db = mHelper.getWritableDatabase(); @@ -229,7 +228,7 @@ public class NotesProvider extends ContentProvider {//定义URL以及匹配规 } @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {//更新 + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int count = 0; String id = null; SQLiteDatabase db = mHelper.getWritableDatabase(); diff --git a/src/main/java/net/micode/notes/gtask/data/MetaData.java b/src/main/java/net/micode/notes/gtask/data/MetaData.java index e713ad7..3a2050b 100644 --- a/src/main/java/net/micode/notes/gtask/data/MetaData.java +++ b/src/main/java/net/micode/notes/gtask/data/MetaData.java @@ -24,8 +24,8 @@ import net.micode.notes.tool.GTaskStringUtils; import org.json.JSONException; import org.json.JSONObject; -//主要是定义用于处理元数据 -public class MetaData extends Task {//继承task,是task的子类 + +public class MetaData extends Task { private final static String TAG = MetaData.class.getSimpleName(); private String mRelatedGid = null; @@ -34,7 +34,7 @@ public class MetaData extends Task {//继承task,是task的子类 try { metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid); } catch (JSONException e) { - Log.e(TAG, "failed to put related gid");//记录错误日志 + Log.e(TAG, "failed to put related gid"); } setNotes(metaInfo.toString()); setName(GTaskStringUtils.META_NOTE_NAME); @@ -47,10 +47,10 @@ public class MetaData extends Task {//继承task,是task的子类 @Override public boolean isWorthSaving() { return getNotes() != null; - }//用于判断数据是否值得保存 + } @Override - public void setContentByRemoteJSON(JSONObject js) {//用远程的json设置内容,基础操作元 + public void setContentByRemoteJSON(JSONObject js) { super.setContentByRemoteJSON(js); if (getNotes() != null) { try { @@ -64,9 +64,9 @@ public class MetaData extends Task {//继承task,是task的子类 } @Override - public void setContentByLocalJSON(JSONObject js) {//这几个函数都是通过一部分已知的项推算其他未知的 + public void setContentByLocalJSON(JSONObject js) { // this function should not be called - throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called");//抛出了IllegalAccessError异常,表明它不应该被直接调用 + throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called"); } @Override diff --git a/src/main/java/net/micode/notes/gtask/data/Node.java b/src/main/java/net/micode/notes/gtask/data/Node.java index c520c06..63950e0 100644 --- a/src/main/java/net/micode/notes/gtask/data/Node.java +++ b/src/main/java/net/micode/notes/gtask/data/Node.java @@ -20,7 +20,7 @@ import android.database.Cursor; import org.json.JSONObject; -public abstract class Node {//主要定义一些获取属性值的方法 +public abstract class Node { public static final int SYNC_ACTION_NONE = 0; public static final int SYNC_ACTION_ADD_REMOTE = 1; @@ -38,7 +38,6 @@ public abstract class Node {//主要定义一些获取属性值的方法 public static final int SYNC_ACTION_UPDATE_CONFLICT = 7; public static final int SYNC_ACTION_ERROR = 8; - //为不同的同步类型添加调用编号 private String mGid; @@ -46,7 +45,7 @@ public abstract class Node {//主要定义一些获取属性值的方法 private long mLastModified; - private boolean mDeleted;//设置基础值,定义获取参数的方法 + private boolean mDeleted; public Node() { mGid = null; @@ -65,9 +64,9 @@ public abstract class Node {//主要定义一些获取属性值的方法 public abstract JSONObject getLocalJSONFromContent(); - public abstract int getSyncAction(Cursor c);//根据当前指针刷新缓冲区 + public abstract int getSyncAction(Cursor c); - public void setGid(String gid) {//定义各项简单查询操作的返回值 + public void setGid(String gid) { this.mGid = gid; } @@ -83,7 +82,7 @@ public abstract class Node {//主要定义一些获取属性值的方法 this.mDeleted = deleted; } - public String getGid() {//this保证指向的还是当前的对象 + public String getGid() { return this.mGid; } diff --git a/src/main/java/net/micode/notes/gtask/data/SqlData.java b/src/main/java/net/micode/notes/gtask/data/SqlData.java index 7fdfd17..d3ec3be 100644 --- a/src/main/java/net/micode/notes/gtask/data/SqlData.java +++ b/src/main/java/net/micode/notes/gtask/data/SqlData.java @@ -71,9 +71,9 @@ public class SqlData { private ContentValues mDiffDataValues; - public SqlData(Context context) {//初始化对象,用于存储数据 + public SqlData(Context context) { mContentResolver = context.getContentResolver(); - mIsCreate = true;//一类型的变量为true + mIsCreate = true; mDataId = INVALID_ID; mDataMimeType = DataConstants.NOTE; mDataContent = ""; @@ -82,14 +82,14 @@ public class SqlData { mDiffDataValues = new ContentValues(); } - public SqlData(Context context, Cursor c) {//同样是存储数据,另外定义支持冲cursor读入 + public SqlData(Context context, Cursor c) { mContentResolver = context.getContentResolver(); - mIsCreate = false;//二类型的变量为false + mIsCreate = false; loadFromCursor(c); mDiffDataValues = new ContentValues(); } - private void loadFromCursor(Cursor c) {//上面用到的从cursor读取的函数,从存储的各个列获取数据 + private void loadFromCursor(Cursor c) { mDataId = c.getLong(DATA_ID_COLUMN); mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN); mDataContent = c.getString(DATA_CONTENT_COLUMN); @@ -97,9 +97,9 @@ public class SqlData { mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN); } - public void setContent(@androidx.annotation.NonNull JSONObject js) throws JSONException {//获取json类型的参数,并且根据它更新自定义的数据单元中的值 - long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;//如果有id直接赋值,没有则需要在获取 - if (mIsCreate || mDataId != dataId) {//初始未设置的数据单元通过它设置内容,通过cursor产生的数据元可通过它完成更新 + public void setContent(JSONObject js) throws JSONException { + long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID; + if (mIsCreate || mDataId != dataId) { mDiffDataValues.put(DataColumns.ID, dataId); } mDataId = dataId; @@ -131,7 +131,7 @@ public class SqlData { } public JSONObject getContent() throws JSONException { - if (mIsCreate) {//同样的只有通过cursor产生的数据单元可通过这个函数获取数据 + if (mIsCreate) { Log.e(TAG, "it seems that we haven't created this in database yet"); return null; } @@ -144,7 +144,7 @@ public class SqlData { return js; } - public void commit(long noteId, boolean validateVersion, long version) {//提交数据,并且打上类似于标签的版本号以及验证值 + public void commit(long noteId, boolean validateVersion, long version) { if (mIsCreate) { if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) { @@ -162,10 +162,10 @@ public class SqlData { } else { if (mDiffDataValues.size() > 0) { int result = 0; - if (!validateVersion) { // 不验证版本的情况下,直接使用ContentResolver更新指定ID的数据 + if (!validateVersion) { result = mContentResolver.update(ContentUris.withAppendedId( Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null); - } else { // 需要验证版本的情况下,使用ContentResolver进行条件更新操作 + } else { result = mContentResolver.update(ContentUris.withAppendedId( Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, " ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE diff --git a/src/main/java/net/micode/notes/gtask/data/SqlNote.java b/src/main/java/net/micode/notes/gtask/data/SqlNote.java index 48891a6..79a4095 100644 --- a/src/main/java/net/micode/notes/gtask/data/SqlNote.java +++ b/src/main/java/net/micode/notes/gtask/data/SqlNote.java @@ -122,7 +122,7 @@ public class SqlNote { private ArrayList mDataList; - public SqlNote(Context context) {//定义数据单元存储数据 + public SqlNote(Context context) { mContext = context; mContentResolver = context.getContentResolver(); mIsCreate = true; @@ -135,7 +135,7 @@ public class SqlNote { mParentId = 0; mSnippet = ""; mType = Notes.TYPE_NOTE; - mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;//直接从设置的属性中获取值 + mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; mWidgetType = Notes.TYPE_WIDGET_INVALIDE; mOriginParent = 0; mVersion = 0; @@ -147,14 +147,14 @@ public class SqlNote { mContext = context; mContentResolver = context.getContentResolver(); mIsCreate = false; - loadFromCursor(c);//从cursor中直接获取变量值 + loadFromCursor(c); mDataList = new ArrayList(); if (mType == Notes.TYPE_NOTE) loadDataContent(); mDiffNoteValues = new ContentValues(); } - public SqlNote(Context context, long id) {//根据id初始化数据单元 + public SqlNote(Context context, long id) { mContext = context; mContentResolver = context.getContentResolver(); mIsCreate = false; @@ -175,7 +175,7 @@ public class SqlNote { }, null); if (c != null) { c.moveToNext(); - loadFromCursor(c);//通过调用减少重复代码编写 + loadFromCursor(c); } else { Log.w(TAG, "loadFromCursor: cursor = null"); } @@ -185,7 +185,7 @@ public class SqlNote { } } - private void loadFromCursor(Cursor c) {//直接使用get获得变量值 + private void loadFromCursor(Cursor c) { mId = c.getLong(ID_COLUMN); mAlertDate = c.getLong(ALERTED_DATE_COLUMN); mBgColorId = c.getInt(BG_COLOR_ID_COLUMN); @@ -200,7 +200,7 @@ public class SqlNote { mVersion = c.getLong(VERSION_COLUMN); } - private void loadDataContent() {//这个函数判别查询的数据是否存在,并且读取到数据列表中存储 + private void loadDataContent() { Cursor c = null; mDataList.clear(); try { @@ -210,12 +210,12 @@ public class SqlNote { }, null); if (c != null) { if (c.getCount() == 0) { - Log.w(TAG, "it seems that the note has not data");//遇到文件为空抛出对应的异常 + Log.w(TAG, "it seems that the note has not data"); return; } while (c.moveToNext()) { SqlData data = new SqlData(mContext, c); - mDataList.add(data);//向Datalist中加入读取到的数据 + mDataList.add(data); } } else { Log.w(TAG, "loadDataContent: cursor = null"); @@ -226,8 +226,7 @@ public class SqlNote { } } - public boolean setContent(JSONObject js) {//设置数据单元中变量的值 - //如果所需的值存在,直接赋值使用,否则再先进行一步读取 + public boolean setContent(JSONObject js) { try { JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) { @@ -360,7 +359,7 @@ public class SqlNote { return true; } - public JSONObject getContent() {//直接读取的方式将所需的数据读到对应变量 + public JSONObject getContent() { try { JSONObject js = new JSONObject(); @@ -413,7 +412,6 @@ public class SqlNote { mDiffNoteValues.put(NoteColumns.PARENT_ID, id); } - //定义一些简单的获取取值的方法 public void setGtaskId(String gid) { mDiffNoteValues.put(NoteColumns.GTASK_ID, gid); } @@ -442,7 +440,7 @@ public class SqlNote { return mType == Notes.TYPE_NOTE; } - public void commit(boolean validateVersion) {//将数据做一定修改提交 + public void commit(boolean validateVersion) { if (mIsCreate) { if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) { mDiffNoteValues.remove(NoteColumns.ID); diff --git a/src/main/java/net/micode/notes/gtask/data/Task.java b/src/main/java/net/micode/notes/gtask/data/Task.java index 4d68293..6a19454 100644 --- a/src/main/java/net/micode/notes/gtask/data/Task.java +++ b/src/main/java/net/micode/notes/gtask/data/Task.java @@ -32,7 +32,7 @@ import org.json.JSONException; import org.json.JSONObject; -public class Task extends Node {//继承Node类的属性 +public class Task extends Node { private static final String TAG = Task.class.getSimpleName(); private boolean mCompleted; @@ -54,7 +54,7 @@ public class Task extends Node {//继承Node类的属性 mMetaInfo = null; } - public JSONObject getCreateAction(int actionId) {//创建一个初始的任务对象,并对它赋初值 + public JSONObject getCreateAction(int actionId) { JSONObject js = new JSONObject(); try { @@ -103,7 +103,7 @@ public class Task extends Node {//继承Node类的属性 return js; } - public JSONObject getUpdateAction(int actionId) {//更新任务 + public JSONObject getUpdateAction(int actionId) { JSONObject js = new JSONObject(); try { @@ -120,7 +120,7 @@ public class Task extends Node {//继承Node类的属性 // entity_delta JSONObject entity = new JSONObject(); entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); - if (getNotes() != null) {//如果笔记不为空,更新笔记 + if (getNotes() != null) { entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes()); } entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); @@ -135,11 +135,11 @@ public class Task extends Node {//继承Node类的属性 return js; } - public void setContentByRemoteJSON(JSONObject js) {//通过远端的json设置内容的值 + public void setContentByRemoteJSON(JSONObject js) { if (js != null) { try { // id - if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {//如果值已经被json对象所具备,则直接进行设置 + if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); } @@ -175,7 +175,7 @@ public class Task extends Node {//继承Node类的属性 } } - public void setContentByLocalJSON(JSONObject js) {//通过本地的json文件来设置内容 + public void setContentByLocalJSON(JSONObject js) { if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE) || !js.has(GTaskStringUtils.META_HEAD_DATA)) { Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); @@ -204,7 +204,7 @@ public class Task extends Node {//继承Node类的属性 } } - public JSONObject getLocalJSONFromContent() {//通过本地的内容,生成json文件 + public JSONObject getLocalJSONFromContent() { String name = getName(); try { if (mMetaInfo == null) { @@ -216,7 +216,7 @@ public class Task extends Node {//继承Node类的属性 JSONObject js = new JSONObject(); JSONObject note = new JSONObject(); - JSONArray dataArray = new JSONArray();//声明所有所要用到的变量 + JSONArray dataArray = new JSONArray(); JSONObject data = new JSONObject(); data.put(DataColumns.CONTENT, name); dataArray.put(data); @@ -227,7 +227,7 @@ public class Task extends Node {//继承Node类的属性 } else { // synced task JSONObject note = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); - JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA);//提取出所有的信息 + JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA); for (int i = 0; i < dataArray.length(); i++) { JSONObject data = dataArray.getJSONObject(i); @@ -258,11 +258,11 @@ public class Task extends Node {//继承Node类的属性 } } - public int getSyncAction(Cursor c) {//同步缓存 + public int getSyncAction(Cursor c) { try { JSONObject noteInfo = null; if (mMetaInfo != null && mMetaInfo.has(GTaskStringUtils.META_HEAD_NOTE)) { - noteInfo = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);//更新到最新的笔记信息 + noteInfo = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); } if (noteInfo == null) { @@ -311,14 +311,14 @@ public class Task extends Node {//继承Node类的属性 return SYNC_ACTION_ERROR; } - public boolean isWorthSaving() {//只要有信息就认为是值得保存的,返回true + public boolean isWorthSaving() { return mMetaInfo != null || (getName() != null && getName().trim().length() > 0) || (getNotes() != null && getNotes().trim().length() > 0); } public void setCompleted(boolean completed) { this.mCompleted = completed; - }//进行前面使用过的调用函数返回值的对应 + } public void setNotes(String notes) { this.mNotes = notes; diff --git a/src/main/java/net/micode/notes/gtask/data/TaskList.java b/src/main/java/net/micode/notes/gtask/data/TaskList.java index 95d6bf5..4ea21c5 100644 --- a/src/main/java/net/micode/notes/gtask/data/TaskList.java +++ b/src/main/java/net/micode/notes/gtask/data/TaskList.java @@ -30,17 +30,17 @@ import org.json.JSONObject; import java.util.ArrayList; -public class TaskList extends Node {//同Task一样,继承了Node +public class TaskList extends Node { private static final String TAG = TaskList.class.getSimpleName(); private int mIndex; - private ArrayList mChildren;//内部含有一个Task的列,是任务的序列 + private ArrayList mChildren; public TaskList() { super(); mChildren = new ArrayList(); - mIndex = 1;//初始化 + mIndex = 1; } public JSONObject getCreateAction(int actionId) { @@ -74,7 +74,7 @@ public class TaskList extends Node {//同Task一样,继承了Node return js; } - public JSONObject getUpdateAction(int actionId) {//更新行动与Task中定义的基本一样 + public JSONObject getUpdateAction(int actionId) { JSONObject js = new JSONObject(); try { @@ -104,7 +104,7 @@ public class TaskList extends Node {//同Task一样,继承了Node } public void setContentByRemoteJSON(JSONObject js) { - if (js != null) {//类似的通过远端更新内容 + if (js != null) { try { // id if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { @@ -129,7 +129,7 @@ public class TaskList extends Node {//同Task一样,继承了Node } } - public void setContentByLocalJSON(JSONObject js) {//通过本地文件更新内容 + public void setContentByLocalJSON(JSONObject js) { if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) { Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); } @@ -215,26 +215,26 @@ public class TaskList extends Node {//同Task一样,继承了Node return SYNC_ACTION_ERROR; } -//以上都与task定义类似 + public int getChildTaskCount() { return mChildren.size(); } public boolean addChildTask(Task task) { boolean ret = false; - if (task != null && !mChildren.contains(task)) {//任务不为空,并且还不在列表中,则将其加入 + if (task != null && !mChildren.contains(task)) { ret = mChildren.add(task); - if (ret) {//成功加入以后继续设置关系 + if (ret) { // need to set prior sibling and parent task.setPriorSibling(mChildren.isEmpty() ? null : mChildren .get(mChildren.size() - 1)); - task.setParent(this);//设置任务的父子关系 + task.setParent(this); } } return ret; } - public boolean addChildTask(Task task, int index) {//更进一步的实现在指定索引位置插入任务 + public boolean addChildTask(Task task, int index) { if (index < 0 || index > mChildren.size()) { Log.e(TAG, "add child task: invalid index"); return false; @@ -260,9 +260,9 @@ public class TaskList extends Node {//同Task一样,继承了Node return true; } - public boolean removeChildTask(Task task) {//移除子任务 + public boolean removeChildTask(Task task) { boolean ret = false; - int index = mChildren.indexOf(task);//查找其索引 + int index = mChildren.indexOf(task); if (index != -1) { ret = mChildren.remove(task); @@ -281,7 +281,7 @@ public class TaskList extends Node {//同Task一样,继承了Node return ret; } - public boolean moveChildTask(Task task, int index) {//定向移除对应位置的任务 + public boolean moveChildTask(Task task, int index) { if (index < 0 || index >= mChildren.size()) { Log.e(TAG, "move child task: invalid index"); @@ -299,7 +299,7 @@ public class TaskList extends Node {//同Task一样,继承了Node return (removeChildTask(task) && addChildTask(task, index)); } - public Task findChildTaskByGid(String gid) {//通过Gid查找任务 + public Task findChildTaskByGid(String gid) { for (int i = 0; i < mChildren.size(); i++) { Task t = mChildren.get(i); if (t.getGid().equals(gid)) { @@ -309,7 +309,7 @@ public class TaskList extends Node {//同Task一样,继承了Node return null; } - public int getChildTaskIndex(Task task) {//获取任务对应的索引 + public int getChildTaskIndex(Task task) { return mChildren.indexOf(task); } @@ -323,7 +323,7 @@ public class TaskList extends Node {//同Task一样,继承了Node public Task getChilTaskByGid(String gid) { for (Task task : mChildren) { - if (task.getGid().equals(gid))//找到一个gid相符的即为所要的任务 + if (task.getGid().equals(gid)) return task; } return null; diff --git a/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java b/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java index 937be4b..15504be 100644 --- a/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java +++ b/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java @@ -15,26 +15,18 @@ */ package net.micode.notes.gtask.exception; -/** - * @method: ActionFailureException - * @description:ActionFailureException 继承了 RuntimeException 类,用于扩展抛错机制,显示具体错误类型 - * 这个类采取直接执行父类构造方法来完成类的构造,总计完成了有参数以及无参数情况下的三种构造方法 - * 定义了私有参数serialVersionUID,是序列化,用于验证版本一致性 - * @date: 11:05 - * @author: Xia Yanbo -*/ public class ActionFailureException extends RuntimeException { - private static final long serialVersionUID = 4425249765923293627L;//序列化,用于验证版本一致性 - //构造方法 + private static final long serialVersionUID = 4425249765923293627L; + public ActionFailureException() { - super();//用构造方法赋初值,调用父类无参数的构造方法 + super(); } - //构造方法 + public ActionFailureException(String paramString) { - super(paramString);//调用父类有参数的构造方法 + super(paramString); } - //构造方法 + public ActionFailureException(String paramString, Throwable paramThrowable) { super(paramString, paramThrowable); } diff --git a/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java b/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java index 0e30963..b08cfb1 100644 --- a/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java +++ b/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java @@ -14,32 +14,20 @@ * limitations under the License. */ -package net.micode.notes.gtask.exception;//调用完成异常处理 -/** - * @method: NetworkFailureException - * @description:NetworkFailureException 继承了 Exception 类,用于扩展抛错机制,显示具体错误类型 - * 这个类采取直接执行父类构造方法来完成类的构造,总计完成了有参数以及无参数情况下的三种构造方法 - * //定义了私有参数serialVersionUID,是序列化,用于验证版本一致性 - * @date: 11:07 - * @author: Xia Yanbo - * @param: - * @param: - * @param: -*/ +package net.micode.notes.gtask.exception; public class NetworkFailureException extends Exception { - private static final long serialVersionUID = 2107610287180234136L;//序列化,用于验证版本一致性 - //构造方法 + private static final long serialVersionUID = 2107610287180234136L; + public NetworkFailureException() { - super();//用构造方法赋初值,调用父类无参数的构造方法 + super(); } - //构造方法 + public NetworkFailureException(String paramString) { - super(paramString);//调用父类有参数的构造方法 + super(paramString); } - //构造方法 + public NetworkFailureException(String paramString, Throwable paramThrowable) { super(paramString, paramThrowable); } } - diff --git a/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java b/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java index b5a9e75..0ea27b7 100644 --- a/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java +++ b/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java @@ -29,21 +29,10 @@ import net.micode.notes.ui.NotesListActivity; import net.micode.notes.ui.NotesPreferenceActivity; -/** - * @method: GTaskASyncTask - * @description:GTaskASyncTask 类继承 AsyncTask 类而来,负责同步任务读取的账户准备, - * 完成消息报文的读取,取消任务同步,以及显示任务的进度信息,完成信息的任务。 - * 总计定义了4个私有的变量 - * mcontext 用于访问特定资源和类的context对象 - * mOnCompleteListener 回调接口,将传递结果给调用者 - * mNotifiManager 通过调用 mTaskManager 控制和调度异步任务 - * @date: 9:01 - * @author: Xia Yanbo -*/ public class GTaskASyncTask extends AsyncTask { - private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;//序列化,用于验证版本 -//声明定义一个接口OnCompleteListener,实现放在后面 + private static int GTASK_SYNC_NOTIFICATION_ID = 5234235; + public interface OnCompleteListener { void onComplete(); } @@ -55,16 +44,7 @@ public class GTaskASyncTask extends AsyncTask { private GTaskManager mTaskManager; private OnCompleteListener mOnCompleteListener; -/** - * @method: GTaskASyncTask - * @description:GTaskASyncTask类的构造函数,完成构造 - * @date: 16:11 - * @author: Xia Yanbo - * @param: mcontext 用于访问特定资源和类的context对象 - * @param: mOnCompleteListener 回调接口,将传递结果给调用者 - * @param: mNotifiManager 通过调用 - * @param: mTaskManager 控制和调度异步任务 -*/ + public GTaskASyncTask(Context context, OnCompleteListener listener) { mContext = context; mOnCompleteListener = listener; @@ -72,42 +52,22 @@ public class GTaskASyncTask extends AsyncTask { .getSystemService(Context.NOTIFICATION_SERVICE); mTaskManager = GTaskManager.getInstance(); } - /** - * @method: GTaskASyncTask - * @description:取消异步任务 - * @date: 8:32 - * @author: Xia Yanbo - */ + public void cancelSync() { mTaskManager.cancelSync(); } - /** - * @method: GTaskASyncTask - * @description:更新异步任务的进度 - * @date: 8:33 - * @author: Xia Yanbo - * @param: message 进度的报文 - */ public void publishProgess(String message) { publishProgress(new String[] { message }); } - /** - * @method: GTaskASyncTask - * @description:显示系统通知 - * @date: 8:35 - * @author: Xia Yanbo - * @param:tickerId通知的文本资源的ID - * @param:content通知的具体文本内容 - * @return:NULL - */ + private void showNotification(int tickerId, String content) { Notification notification = new Notification(R.drawable.notification, mContext .getString(tickerId), System.currentTimeMillis()); notification.defaults = Notification.DEFAULT_LIGHTS; - notification.flags = Notification.FLAG_AUTO_CANCEL;//打上标识,用于判断发送报错信息和通知操作等 + notification.flags = Notification.FLAG_AUTO_CANCEL; PendingIntent pendingIntent; if (tickerId != R.string.ticker_success) { pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, @@ -119,43 +79,24 @@ public class GTaskASyncTask extends AsyncTask { } // notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content, // pendingIntent); - mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);//直接调用父类的方法 + mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification); } - /** - * @method: GTaskASyncTask - * @description:运行在后台,执行同步操作前准备 - * @date: 8:46 - * @author: Xia Yanbo - * @return: 状态码,用于检验同步是否完成 - */ + @Override protected Integer doInBackground(Void... unused) { publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity - .getSyncAccountName(mContext)));//获取用户的状态信息 + .getSyncAccountName(mContext))); return mTaskManager.sync(mContext, this); } - /** - * @method: GTaskASyncTask - * @description:同步过程中发送传输同步信息的报文 - * @date: 8:50 - * @author: Xia Yanbo - * @param:Progress 正在进行的任务的进度信息 - */ + @Override protected void onProgressUpdate(String... progress) { - showNotification(R.string.ticker_syncing, progress[0]);//显示正在进行同步操作的通知 - if (mContext instanceof GTaskSyncService) {//检查是否是GTaskSyncService的实例。 + showNotification(R.string.ticker_syncing, progress[0]); + if (mContext instanceof GTaskSyncService) { ((GTaskSyncService) mContext).sendBroadcast(progress[0]); - // 如果是,就调用该服务的sendBroadcast方法发送广播,通知其他组件同步的进度。 } } - /** - * @method: GTaskASyncTask - * @description:将执行完毕的任务的完成信息,错误信息以及取消信息显示出来 - * @date: 8:57 - * @author: Xia Yanbo - * @param:result 进程运行的结果信息 - */ + @Override protected void onPostExecute(Integer result) { if (result == GTaskManager.STATE_SUCCESS) { @@ -170,7 +111,7 @@ public class GTaskASyncTask extends AsyncTask { showNotification(R.string.ticker_cancel, mContext .getString(R.string.error_sync_cancelled)); } - if (mOnCompleteListener != null) {//如果监听到了报文,创建一个新的线程来通知任务完成(减少主进程时间浪费) + if (mOnCompleteListener != null) { new Thread(new Runnable() { public void run() { diff --git a/src/main/java/net/micode/notes/model/Note.java b/src/main/java/net/micode/notes/model/Note.java index bf32ddf..6706cf6 100644 --- a/src/main/java/net/micode/notes/model/Note.java +++ b/src/main/java/net/micode/notes/model/Note.java @@ -33,102 +33,78 @@ import net.micode.notes.data.Notes.TextNote; import java.util.ArrayList; -/** - * @classname: Note - * @description:完成便签的创建以及便签后续的更新操作(设置属性值,完成数据同步) - * 允许批量执行操作,可以将便签放至内存存储器中 - * @date: 2024/1/2 21:31 - * @author: Xia Yanbo -*/ + public class Note { private ContentValues mNoteDiffValues; private NoteData mNoteData; private static final String TAG = "Note"; /** * Create a new note id for adding a new note to databases - * @classname: Note - * @description:创建或者修改一个新的便签 - * @date: 2024/1/2 20:36 - * @author: Xia Yanbo - * @param:context上下文 - * @param:folderId 所属包的id - * @return:noteID新笔记记录的id */ - public static synchronized long getNewNoteId(Context context, long folderId) {//控制类的所有实例的并发访问 + public static synchronized long getNewNoteId(Context context, long folderId) { // Create a new note in the database - //初始化变量的信息 ContentValues values = new ContentValues(); long createdTime = System.currentTimeMillis(); - values.put(NoteColumns.CREATED_DATE, createdTime);//创建时间 - values.put(NoteColumns.MODIFIED_DATE, createdTime);//修改时间 - values.put(NoteColumns.TYPE, Notes.TYPE_NOTE);//便签类型 - values.put(NoteColumns.LOCAL_MODIFIED, 1);//本地修改位,表示在本地被修改过与否 - values.put(NoteColumns.PARENT_ID, folderId);//所属包的id - Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values);//插入新的便签记录(标记) + values.put(NoteColumns.CREATED_DATE, createdTime); + values.put(NoteColumns.MODIFIED_DATE, createdTime); + values.put(NoteColumns.TYPE, Notes.TYPE_NOTE); + values.put(NoteColumns.LOCAL_MODIFIED, 1); + values.put(NoteColumns.PARENT_ID, folderId); + Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values); long noteId = 0; try { - noteId = Long.valueOf(uri.getPathSegments().get(1));//获取新笔记纪录的id - } catch (NumberFormatException e) {//获取失败报错 + noteId = Long.valueOf(uri.getPathSegments().get(1)); + } catch (NumberFormatException e) { Log.e(TAG, "Get note id error :" + e.toString()); noteId = 0; } - //如果noteid为-1抛出id错误的信息 if (noteId == -1) { throw new IllegalStateException("Wrong note id:" + noteId); } return noteId; } - //初始化定义两个变量用来存储便签的数据,一个是存储便签属性、一个是存储便签内容 + public Note() { - mNoteDiffValues = new ContentValues();//便签属性 - mNoteData = new NoteData();//便签内容 + mNoteDiffValues = new ContentValues(); + mNoteData = new NoteData(); } - //设置便签的属性 + public void setNoteValue(String key, String value) { - mNoteDiffValues.put(key, value);//键值,id - mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);//本地编辑修改位 - mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());//修改日期 + 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(); } - /** - * @classname: Note - * @methodname syncNote - * @description:同步便签 - * @date: 2024/1/2 20:54 - * @author: Xia Yanbo - * @param:context - * @param:noteid便签的id号 - * @return:boolean返回更新是否正确完成 - */ + public boolean syncNote(Context context, long noteId) { if (noteId <= 0) { throw new IllegalArgumentException("Wrong note id:" + noteId); } - //没有修改过则不需要更新 + if (!isLocalModified()) { return true; } @@ -136,7 +112,7 @@ public class Note { /** * In theory, once data changed, the note should be updated on {@link NoteColumns#LOCAL_MODIFIED} and * {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the - * note data info数据发生变化则更新数据(标记) + * note data info */ if (context.getContentResolver().update( ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null, @@ -144,8 +120,8 @@ public class Note { Log.e(TAG, "Update note error, should not happen"); // Do not return, fall through } - mNoteDiffValues.clear();//清除属性 - //如果笔记在本地被修改过,并且推送至ContentResolver失败,则返回false + mNoteDiffValues.clear(); + if (mNoteData.isLocalModified() && (mNoteData.pushIntoContentResolver(context, noteId) == null)) { return false; @@ -155,97 +131,86 @@ public class Note { } private class NoteData { - private long mTextDataId;//文本数据的id + private long mTextDataId; + + private ContentValues mTextDataValues; - private ContentValues mTextDataValues;//存储文本数据的键值对 + private long mCallDataId; - private long mCallDataId;//通话数据的id + private ContentValues mCallDataValues; - private ContentValues mCallDataValues;//存储通话数据 + private static final String TAG = "NoteData"; - private static final String TAG = "NoteData";//记录标签,为日志记录打上标签。 - //给新来的见证便签的键值以及id public NoteData() { mTextDataValues = new ContentValues(); mCallDataValues = new ContentValues(); mTextDataId = 0; 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"); } mTextDataId = id; } - //设置通话数据的id + void setCallDataId(long id) { if (id <= 0) { throw new IllegalArgumentException("Call data id should larger than 0"); } mCallDataId = id; } - //设置通话数据的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()); } - /** - * @classname: NoteData - * @methodname pushIntoContentResolver - * @description:将笔记中的内容放至内容存储器当中,执行所有待执行的动作 - * @date: 2024/1/2 21:10 - * @author: Xia Yanbo - * @param:noteId便签id - * @param:context存了文本的上下文 - * @return:uri更新过数据后的标识符 - */ + Uri pushIntoContentResolver(Context context, long noteId) { /** * Check for safety */ - //检查笔记的id是否正确 if (noteId <= 0) { throw new IllegalArgumentException("Wrong note id:" + noteId); } - //创建行动列表 + ArrayList operationList = new ArrayList(); ContentProviderOperation.Builder builder = null; - //如果文本数据不为空,进行更新操作 + if(mTextDataValues.size() > 0) { mTextDataValues.put(DataColumns.NOTE_ID, noteId); - // 如果文本数据ID为0,说明是新插入的数据 if (mTextDataId == 0) { mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE); Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, - mTextDataValues);//设置对应的关键键值,插入新的文本数据 + mTextDataValues); try { - setTextDataId(Long.valueOf(uri.getPathSegments().get(1)));//获取数据的id - } catch (NumberFormatException e) {//获取失败打印错误信息 + setTextDataId(Long.valueOf(uri.getPathSegments().get(1))); + } catch (NumberFormatException e) { Log.e(TAG, "Insert new text data fail with noteId" + noteId); mTextDataValues.clear(); return null; } - } else {//创建一个更新操作,并设置更新的数据和条件 + } else { builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( Notes.CONTENT_DATA_URI, mTextDataId)); builder.withValues(mTextDataValues); - operationList.add(builder.build());//将更新操作添加到操作列表中 + operationList.add(builder.build()); } mTextDataValues.clear(); } - //同理如果通信数据不为空,进行更新操作 + if(mCallDataValues.size() > 0) { mCallDataValues.put(DataColumns.NOTE_ID, noteId); if (mCallDataId == 0) { @@ -267,19 +232,19 @@ public class Note { } mCallDataValues.clear(); } - //行动列表非空 + if (operationList.size() > 0) { - try { // 使用内容解析器(ContentResolver)的applyBatch方法来批量执行操作列表中的操作 + try { ContentProviderResult[] results = context.getContentResolver().applyBatch( Notes.AUTHORITY, operationList); return (results == null || results.length == 0 || results[0] == null) ? null - : ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId);//返回操作完成后的结果 + : ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId); } catch (RemoteException e) { Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); return null; } catch (OperationApplicationException e) { Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); - return null;//报错反馈 + return null; } } return null; diff --git a/src/main/java/net/micode/notes/model/WorkingNote.java b/src/main/java/net/micode/notes/model/WorkingNote.java index 460c7d2..be081e4 100644 --- a/src/main/java/net/micode/notes/model/WorkingNote.java +++ b/src/main/java/net/micode/notes/model/WorkingNote.java @@ -31,43 +31,37 @@ import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.TextNote; import net.micode.notes.tool.ResourceParser.NoteBgResources; -/** - * @classname: WorkingNote - * @description:活动中的便签类,是对正处于用户编辑等工作状态下的便签,可以对于便签做 - * 更新组件,修改内容,设置提醒,背景颜色修改等在便签内进行文本编辑工作时可以进行的操作 - * @date: 2024/1/4 11:03 - * @author: Xia Yanbo -*/ + public class WorkingNote { // Note for the working note - private Note mNote;//便签对象 + private Note mNote; // Note Id - private long mNoteId;//便签的id + private long mNoteId; // Note content - private String mContent;//内容字符串 + private String mContent; // Note mode - private int mMode;//便签所处的模式(任务清单/普通) + private int mMode; + + private long mAlertDate; - private long mAlertDate;//提醒时间 + private long mModifiedDate; - private long mModifiedDate;//修改日期 + private int mBgColorId; - private int mBgColorId;//背景颜色 + private int mWidgetId; - private int mWidgetId;//小插件的id号 + private int mWidgetType; - private int mWidgetType;//小插件的类型 + private long mFolderId; - private long mFolderId;//所属便签包的id号 + private Context mContext; - private Context mContext;//便签的上下文 + private static final String TAG = "WorkingNote"; - private static final String TAG = "WorkingNote";//用于接收日志的标签 + private boolean mIsDeleted; - private boolean mIsDeleted;//表示是否已经被删除 + private NoteSettingChangedListener mNoteSettingStatusListener; - private NoteSettingChangedListener mNoteSettingStatusListener;//设置一个监听器,监听便签设置的改变 - //定义数据的字段 public static final String[] DATA_PROJECTION = new String[] { DataColumns.ID, DataColumns.CONTENT, @@ -77,7 +71,7 @@ public class WorkingNote { DataColumns.DATA3, DataColumns.DATA4, }; - //定义便签的字段 + public static final String[] NOTE_PROJECTION = new String[] { NoteColumns.PARENT_ID, NoteColumns.ALERTED_DATE, @@ -86,7 +80,7 @@ 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; @@ -94,7 +88,7 @@ public class WorkingNote { 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; @@ -108,38 +102,19 @@ public class WorkingNote { private static final int NOTE_MODIFIED_DATE_COLUMN = 5; // New note construct - /** - * @classname: WorkingNote - * @methodname WorkingNote - * @description:构造函数,构造一个新的便签,完成初始赋值 - * @date: 2024/1/3 19:26 - * @author: Xia Yanbo - * @param:context相关的文本 - * @param:folderId所属包的id - */ private WorkingNote(Context context, long folderId) { mContext = context; mAlertDate = 0; mModifiedDate = System.currentTimeMillis(); mFolderId = folderId; mNote = new Note(); - mNoteId = 0;//初始化笔记id为0 + mNoteId = 0; mIsDeleted = false; mMode = 0; mWidgetType = Notes.TYPE_WIDGET_INVALIDE; } // Existing note construct - /** - * @classname: WorkingNote - * @methodname WorkingNote - * @description:从现有的笔记创建工作中的笔记(被使用) - * @date: 2024/1/3 21:33 - * @author: Xia Yanbo - * @param:context上下文 - * @param:noteId笔记的id号 - * @param:folderId所属文件夹的id - */ private WorkingNote(Context context, long noteId, long folderId) { mContext = context; mNoteId = noteId; @@ -148,23 +123,14 @@ public class WorkingNote { mNote = new Note(); loadNote(); } - /** - * @classname: WorkingNote - * @methodname loadNote - * @description:加载/读取便签 - * @date: 2024/1/3 21:34 - * @author: Xia Yanbo - */ + private void loadNote() { - //查询数据库,获取与给定笔记id关联的笔记 Cursor cursor = mContext.getContentResolver().query( ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null, null, null); if (cursor != null) { - //如果cursor不为空,移动到结果集的第一行 if (cursor.moveToFirst()) { - //从结果集获取各个属性值 mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN); mBgColorId = cursor.getInt(NOTE_BG_COLOR_ID_COLUMN); mWidgetId = cursor.getInt(NOTE_WIDGET_ID_COLUMN); @@ -173,43 +139,33 @@ public class WorkingNote { mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN); } cursor.close(); - } else {//如果找不到关联的笔记抛出异常 + } else { Log.e(TAG, "No note with id:" + mNoteId); throw new IllegalArgumentException("Unable to find note with id " + mNoteId); } - // 调用loadNoteData方法,继续加载与笔记相关的其他数据(标记) loadNoteData(); } - /** - * @classname: WorkingNote - * @methodname loadNoteData - * @description:将便签里的数据加载进去并存储 - * @date: 2024/1/3 21:48 - * @author: Xia Yanbo - */ + private void loadNoteData() { - //查询数据库,获取与给定笔记id关联的笔记 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 { - String type = cursor.getString(DATA_MIME_TYPE_COLUMN);//获取当前笔记的类型 - //如果笔记是普通的笔记,获取笔记内容、模式、id等参数完成赋值 + String type = cursor.getString(DATA_MIME_TYPE_COLUMN); if (DataConstants.NOTE.equals(type)) { mContent = cursor.getString(DATA_CONTENT_COLUMN); mMode = cursor.getInt(DATA_MODE_COLUMN); mNote.setTextDataId(cursor.getLong(DATA_ID_COLUMN)); - } else if (DataConstants.CALL_NOTE.equals(type)) {//如果数据是通话数据,从数据行中直接获取数据id + } else if (DataConstants.CALL_NOTE.equals(type)) { mNote.setCallDataId(cursor.getLong(DATA_ID_COLUMN)); } else { Log.d(TAG, "Wrong note type with type:" + type); } - } while (cursor.moveToNext());//光标移动到下一行 + } while (cursor.moveToNext()); } cursor.close(); } else { @@ -217,7 +173,7 @@ public class WorkingNote { throw new IllegalArgumentException("Unable to find note's data with id " + mNoteId); } } - //创建一个空的便签,设置属性以及资源的id号等等信息 + public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId, int widgetType, int defaultBgColorId) { WorkingNote note = new WorkingNote(context, folderId); @@ -226,17 +182,15 @@ 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()) { - // 如果不在数据库里,根据包的id和上下文获取一个新的笔记ID,如果获取失败则返回false并记录日志 - if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) {//获取失败返回的id是0 + if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) { Log.e(TAG, "Create new note fail with id:" + mNoteId); return false; } @@ -246,7 +200,6 @@ public class WorkingNote { /** * Update widget content if there exist any widget of this note - * 当组件发生变化时,对笔记设置状态的监听器进行更新? */ if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID && mWidgetType != Notes.TYPE_WIDGET_INVALIDE @@ -258,13 +211,12 @@ public class WorkingNote { return false; } } - //检查是否位于数据库中 + public boolean existInDatabase() { return mNoteId > 0; } - //检查便签是否具有保存的价值 + private boolean isWorthSaving() { - //如果在数据库中已经存在而本地没有修改,或者便签已被删除了,或者便签为空,不值得保存 if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent)) || (existInDatabase() && !mNote.isLocalModified())) { return false; @@ -272,11 +224,11 @@ public class WorkingNote { return true; } } - //设置笔记设置状态的监听器为工作状态 + public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) { mNoteSettingStatusListener = l; } - //设置提醒的日期 + public void setAlertDate(long date, boolean set) { if (date != mAlertDate) { mAlertDate = date; @@ -286,7 +238,7 @@ public class WorkingNote { mNoteSettingStatusListener.onClockAlertChanged(date, set); } } - //删除标记值 + public void markDeleted(boolean mark) { mIsDeleted = mark; if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID @@ -295,7 +247,6 @@ public class WorkingNote { } } - //设置背景的颜色id public void setBgColorId(int id) { if (id != mBgColorId) { mBgColorId = id; @@ -305,10 +256,9 @@ public class WorkingNote { mNote.setNoteValue(NoteColumns.BG_COLOR_ID, String.valueOf(id)); } } - //设置任务清单模式 + public void setCheckListMode(int mode) { if (mMode != mode) { - //进行任务清单模式必要组件的的设置 if (mNoteSettingStatusListener != null) { mNoteSettingStatusListener.onCheckListModeChanged(mMode, mode); } @@ -316,7 +266,7 @@ public class WorkingNote { mNote.setTextData(TextNote.MODE, String.valueOf(mMode)); } } - //设定组件相关的类型id等信息 + public void setWidgetType(int type) { if (type != mWidgetType) { mWidgetType = type; @@ -330,25 +280,24 @@ public class WorkingNote { mNote.setNoteValue(NoteColumns.WIDGET_ID, String.valueOf(mWidgetId)); } } - //设置当前工作便签的文本 + public void setWorkingText(String text) { if (!TextUtils.equals(mContent, text)) { - 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; } @@ -392,13 +341,7 @@ public class WorkingNote { public int getWidgetType() { return mWidgetType; } - /** - * @classname: WorkingNote - * @description:接口,进行便签设置状态的监听, - * 并根据状态改变调用相应的背景颜色,任务清单模式,时间提醒,组件更新功能 - * @date: 2024/1/4 9:22 - * @author: Xia Yanbo - */ + public interface NoteSettingChangedListener { /** * Called when the background color of current note has just changed @@ -412,7 +355,6 @@ public class WorkingNote { /** * Call when user create note from widget - * 实际完成的是更新控件并通知调用者的工作 */ void onWidgetChanged(); diff --git a/src/main/java/net/micode/notes/ui/NoteEditActivity.java b/src/main/java/net/micode/notes/ui/NoteEditActivity.java index 20d6f41..412cd14 100644 --- a/src/main/java/net/micode/notes/ui/NoteEditActivity.java +++ b/src/main/java/net/micode/notes/ui/NoteEditActivity.java @@ -1,4 +1,4 @@ -/* +/* 批过了 * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,34 +22,19 @@ import android.app.AlertDialog; import android.app.PendingIntent; import android.app.SearchManager; import android.appwidget.AppWidgetManager; -import android.content.ContentResolver; import android.content.ContentUris; -import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Matrix; import android.graphics.Paint; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Build; import android.os.Bundle; -import android.os.Environment; import android.preference.PreferenceManager; -import android.provider.DocumentsContract; -import android.provider.MediaStore; -import android.text.Editable; import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; import android.text.format.DateUtils; import android.text.style.BackgroundColorSpan; -import android.text.style.ImageSpan; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -58,12 +43,10 @@ import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; -import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.EditText; -import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -82,24 +65,15 @@ import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener; import net.micode.notes.widget.NoteWidgetProvider_2x; import net.micode.notes.widget.NoteWidgetProvider_4x; -import java.io.FileNotFoundException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -/** - * @classname: NoteEditActivity - * @description:NoteEditActivity 继承于 Activity 实现了OnClickListener,NoteSettingChangedListener, OnTextViewChangeListener三个接口 - * 这个类主要完成对菜单功能的定义,显示与实现,是与用户交互的组件的主体 - * @date: 2023/12/27 0:08 - * @author: Xia Yanbo -*/ public class NoteEditActivity extends Activity implements OnClickListener, NoteSettingChangedListener, OnTextViewChangeListener { - //定义视图组件的基本数据(后面出现在了操作菜可选项里) private class HeadViewHolder { public TextView tvModified; @@ -109,7 +83,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, public ImageView ibSetBgColor; } - //颜色可选项的视图——色板的显示 + private static final Map sBgSelectorBtnsMap = new HashMap(); static { sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW); @@ -127,7 +101,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, sBgSelectorSelectionMap.put(ResourceParser.GREEN, R.id.iv_bg_green_select); sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select); } - //字体大小的视图 + private static final Map sFontSizeBtnsMap = new HashMap(); static { sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE); @@ -144,49 +118,37 @@ public class NoteEditActivity extends Activity implements OnClickListener, sFontSelectorSelectionMap.put(ResourceParser.TEXT_SUPER, R.id.iv_super_select); } - private static final String TAG = "NoteEditActivity"; // 用于日志打印的标签,分类接收消息 - - private HeadViewHolder mNoteHeaderHolder; // 列表头视图容器持有者 - - private View mHeadViewPanel; // 头部视图面板 + private static final String TAG = "NoteEditActivity"; - private View mNoteBgColorSelector; // 笔记背景颜色选择器视图 + private HeadViewHolder mNoteHeaderHolder; - private View mFontSizeSelector; // 字体大小选择器视图 + private View mHeadViewPanel; - private EditText mNoteEditor; // 笔记编辑器输入框 + private View mNoteBgColorSelector; - private View mNoteEditorPanel; // 笔记编辑器面板 + private View mFontSizeSelector; - private WorkingNote mWorkingNote; // 当前正在编辑的工作笔记对象 + private EditText mNoteEditor; - private SharedPreferences mSharedPrefs; // 用于存储和检索应用偏好设置的对象 + private View mNoteEditorPanel; - private int mFontSizeId; // 当前选中的字体大小的资源ID + private WorkingNote mWorkingNote; - private static final String PREFERENCE_FONT_SIZE = "pref_font_size"; // 偏好设置中用于保存字体大小的键 + private SharedPreferences mSharedPrefs; + private int mFontSizeId; - private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10; // 快捷方式图标标题的最大长度 + private static final String PREFERENCE_FONT_SIZE = "pref_font_size"; - public static final String TAG_CHECKED = String.valueOf('\u221A'); // 特殊符号,对钩(可能用于任务视图中表示任务已完成) + private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10; - public static final String TAG_UNCHECKED = String.valueOf('\u25A1'); // 特殊符号,空心方块(可能用于任务视图中表示任务未完成) + public static final String TAG_CHECKED = String.valueOf('\u221A'); + public static final String TAG_UNCHECKED = String.valueOf('\u25A1'); - private LinearLayout mEditTextList; // 线性布局,可能用于动态添加或显示多个EditText + private LinearLayout mEditTextList; - private String mUserQuery; // 用户输入的查询字符串 + private String mUserQuery; + private Pattern mPattern; - private Pattern mPattern; // 用于匹配用户查询的正则表达式模式对象 - private final int PHOTO_REQUEST = 1;//请求码 - - /** - * @classname: NoteEditActivity - * @methodname onCreate - * @description:在活动创建之前进行初始化工作:包括视图的准备,资源的加载 - * @date: 2023/12/25 8:34 - * @author: Xia Yanbo - * @param:保存的设置的状态 - */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -197,90 +159,63 @@ public class NoteEditActivity extends Activity implements OnClickListener, return; } initResources(); - - //根据id获取添加图片的按钮 - final ImageButton add_img_btn = (ImageButton) findViewById(R.id.add_img_btn); - //为点击图片按钮设置监听器 - add_img_btn.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Log.d(TAG, "onClick add image button"); - //允许用户插入特殊类型的数据 - Intent loadImage = new Intent(Intent.ACTION_GET_CONTENT); - loadImage.addCategory(Intent.CATEGORY_OPENABLE); - loadImage.setType("image/*"); - startActivityForResult(loadImage, PHOTO_REQUEST); - } - }); } + /** * 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 - * 当重新使用某个活动时,把它恢复到之前离开的状态 */ @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState);//调用父类 - if (savedInstanceState != null && savedInstanceState.containsKey(Intent.EXTRA_UID)) {//检查保存的状态是否为空,是否包含特定意图 + super.onRestoreInstanceState(savedInstanceState); + if (savedInstanceState != null && savedInstanceState.containsKey(Intent.EXTRA_UID)) { Intent intent = new Intent(Intent.ACTION_VIEW); - intent.putExtra(Intent.EXTRA_UID, savedInstanceState.getLong(Intent.EXTRA_UID));//之前保存的意图附加其上 - if (!initActivityState(intent)) { // 调用 initActivityState 方法来处理这个 Intent,可能进行一些初始化工作或状态设置。 - finish(); // 如果 initActivityState 方法返回 false,表示初始化失败,此时结束当前活动。 - return; // 结束当前方法。 + intent.putExtra(Intent.EXTRA_UID, savedInstanceState.getLong(Intent.EXTRA_UID)); + if (!initActivityState(intent)) { + finish(); + return; } Log.d(TAG, "Restoring from killed activity"); } } - /** - * @classname: NoteEditActivity - * @methodname initActivityState - * @description: - * @date: 2023/12/25 8:44 - * @author: Xia Yanbo - * @param:intent意图消息 - * @return: - */ + 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())) {//检查意图是否是查看 + if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) { long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0); mUserQuery = ""; /** * Starting from the searched result - * 如果intent包含额外的数据键 */ if (intent.hasExtra(SearchManager.EXTRA_DATA_KEY)) { - //解析数据键,获取笔记ID以及查询字符串 noteId = Long.parseLong(intent.getStringExtra(SearchManager.EXTRA_DATA_KEY)); mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY); } - //如果笔记id在数据库中不可见 + if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) { Intent jump = new Intent(this, NotesListActivity.class); - startActivity(jump);//跳转到笔记集活动中 + startActivity(jump); showToast(R.string.error_note_not_exist); finish(); return false; } else { - mWorkingNote = WorkingNote.load(this, noteId);//加载笔记对象 - if (mWorkingNote == null) {//如果笔记对象为空,记录错误日志并且结束当前活动 + mWorkingNote = WorkingNote.load(this, noteId); + if (mWorkingNote == null) { Log.e(TAG, "load note failed with note id" + noteId); finish(); return false; } } - // 设置软键盘状态为隐藏,调整窗口大小以适应内容 getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); - } else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) {//否则,意图并非查看的情况 + } else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) { // New note - //获取额外的数据各类ID以及类型等数据 long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0); int widgetId = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); @@ -292,7 +227,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, // 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) {//负责消息通知 + if (callDate != 0 && phoneNumber != null) { if (TextUtils.isEmpty(phoneNumber)) { Log.w(TAG, "The call record number is null"); } @@ -312,7 +247,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, } } else { mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId, widgetType, - bgResId);//电话号码和提醒日期都为空,直接创建新表 + bgResId); } getWindow().setSoftInputMode( @@ -328,33 +263,26 @@ public class NoteEditActivity extends Activity implements OnClickListener, } @Override - //初始化屏幕 protected void onResume() { super.onResume(); initNoteScreen(); } - // 定义一个私有方法initNoteScreen,用于初始化Note屏幕 + private void initNoteScreen() { - // 设置Note编辑器的文本外观,使用指定的字体大小ID(标记,分别更改字体大小的功能可以类似实现) mNoteEditor.setTextAppearance(this, TextAppearanceResources .getTexAppearanceResource(mFontSizeId)); - // 检查当前Note是否处于Check List模式 if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { - // 如果处于Check List模式,调用switchToListMode方法并传入Note的内容 switchToListMode(mWorkingNote.getContent()); } else { - // 如果不是Check List模式,设置Note编辑器的文本为高亮查询结果,并选择文本的末尾 mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery)); mNoteEditor.setSelection(mNoteEditor.getText().length()); } - // 遍历sBgSelectorSelectionMap的键集合,并隐藏对应的视图。 for (Integer id : sBgSelectorSelectionMap.keySet()) { findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE); } - //给资源设置id mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId()); mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId()); - //设置修改日期的显示文本 + mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(this, mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME @@ -364,21 +292,13 @@ public class NoteEditActivity extends Activity implements OnClickListener, * TODO: Add the menu for setting alert. Currently disable it because the DateTimePicker * is not ready */ - //插入之后初始化 - convertToImage(); showAlertHeader(); } - /** - * @classname: NoteEditActivity - * @methodname showAlertHeader - * @description:对于便签里设定的提醒时间,设置显示并在到达时间时发出提醒 - * @date: 2023/12/25 14:45 - * @author: Xia Yanbo - */ + private void showAlertHeader() { if (mWorkingNote.hasClockAlert()) { long time = System.currentTimeMillis(); - if (time > mWorkingNote.getAlertDate()) {//判断时间是否到达 + if (time > mWorkingNote.getAlertDate()) { mNoteHeaderHolder.tvAlertDate.setText(R.string.note_alert_expired); } else { mNoteHeaderHolder.tvAlertDate.setText(DateUtils.getRelativeTimeSpanString( @@ -391,19 +311,12 @@ public class NoteEditActivity extends Activity implements OnClickListener, mNoteHeaderHolder.ivAlertIcon.setVisibility(View.GONE); }; } - //根据新的意图重新初始化活动状态 + @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); initActivityState(intent); } - /** - * @classname: NoteEditActivity - * @methodname onSaveInstanceState - * @description: 未保存到数据库的便签分配ID并保存 - * @date: 2023/12/25 14:59 - * @author: Xia Yanbo - */ @Override protected void onSaveInstanceState(Bundle outState) { @@ -419,15 +332,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId()); Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState"); } - /** - * @classname: NoteEditActivity - * @methodname dispatchTouchEvent - * @description:当触摸事件不在范围内时,选择性隐藏显示的字体和主题颜色窗口选项 - * @date: 2023/12/25 15:10 - * @author: Xia Yanbo - * @param:ev 触摸事件 - * @return:boolean 是否进行隐藏 - */ + @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (mNoteBgColorSelector.getVisibility() == View.VISIBLE @@ -443,36 +348,21 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return super.dispatchTouchEvent(ev); } - /** - * @classname: NoteEditActivity - * @methodname inRangeOfView - * @description:检查触摸时间是否在视图的范围之内 - * @date: 2023/12/25 15:05 - * @author: Xia Yanbo - * @param:view 窗口视图 - * @param:ev 触摸事件 - * @return:boolean在范围内返回true,否则返回false - */ + private boolean inRangeOfView(View view, MotionEvent ev) { int []location = new int[2]; - view.getLocationOnScreen(location);//获取视图在屏幕上的位置 + view.getLocationOnScreen(location); int x = location[0]; int y = location[1]; - if (ev.getX() < x//判断事件有没有在视图所在的范围之内 + if (ev.getX() < x || ev.getX() > (x + view.getWidth()) || ev.getY() < y || ev.getY() > (y + view.getHeight())) { - return false; - } + return false; + } return true; } - /** - * @classname: NoteEditActivity - * @methodname initResources - * @description:初始化资源项,进行便签显示组件的准备与id初始化 - * @date: 2023/12/25 15:13 - * @author: Xia Yanbo - */ + private void initResources() { mHeadViewPanel = findViewById(R.id.note_title); mNoteHeaderHolder = new HeadViewHolder(); @@ -500,14 +390,13 @@ public class NoteEditActivity extends Activity implements OnClickListener, * 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} - * 资源id大小可能会越界,这时返回缺省的BG_DEFAULT_FONT_SIZE */ if(mFontSizeId >= TextAppearanceResources.getResourcesSize()) { mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE; } mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list); } - //一系列输入暂停时,进行便签内容的保存,并输出保存的长度信息 + @Override protected void onPause() { super.onPause(); @@ -516,66 +405,53 @@ public class NoteEditActivity extends Activity implements OnClickListener, } clearSettingState(); } - /** - * @classname: NoteEditActivity - * @methodname updateWidget - * @description:更新控件 - * @date: 2023/12/25 15:17 - * @author: Xia Yanbo - */ + private void updateWidget() { Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); - if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) {//检查当前工作笔记的控件类型,给对应的提供类 + if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) { intent.setClass(this, NoteWidgetProvider_2x.class); } else if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_4X) { intent.setClass(this, NoteWidgetProvider_4x.class); - } else {//控件类型不受支持,打印错误日志 + } else { Log.e(TAG, "Unspported widget type"); return; } intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { - mWorkingNote.getWidgetId()//给意图intent添加要更新的控件的id + mWorkingNote.getWidgetId() }); - sendBroadcast(intent);//通知系统更新小控件 - setResult(RESULT_OK, intent);//通知调用者已完成 + sendBroadcast(intent); + setResult(RESULT_OK, intent); } - /** - * @classname: NoteEditActivity - * @methodname onClick - * @description:通过点击的位置获取工作视图,并进行设置背景色,选择背景色,选择字体大小三种点击事件的处理 - * @date: 2023/12/25 15:30 - * @author: Xia Yanbo - * @param: v视图 - */ + public void onClick(View v) { int id = v.getId(); - if (id == R.id.btn_set_bg_color) {// 如果点击的是设置背景色的按钮 + if (id == R.id.btn_set_bg_color) { mNoteBgColorSelector.setVisibility(View.VISIBLE); findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( - View.VISIBLE);//之前这里报错,已修改,显示背景色选择器 - } else if (sBgSelectorBtnsMap.containsKey(id)) { // 如果点击的是背景色选择器的某个按钮 + - View.VISIBLE); + } else if (sBgSelectorBtnsMap.containsKey(id)) { findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( View.GONE); - mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));// 设置工作笔记的背景色ID为选择的背景色ID + mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id)); mNoteBgColorSelector.setVisibility(View.GONE); - } else if (sFontSizeBtnsMap.containsKey(id)) {// 如果点击的是字体大小选择器的某个按钮 - findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.GONE);// 隐藏当前字体大小选择器 - mFontSizeId = sFontSizeBtnsMap.get(id); // 设置字体大小ID为选择的字体大小ID - mSharedPrefs.edit().putInt(PREFERENCE_FONT_SIZE, mFontSizeId).commit(); // 将字体大小ID保存到SharedPreferences中 - findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);// 显示新的字体大小选择器 - if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { // 如果笔记处于检查列表模式,则获取文本并切换到列表模式(两种模式是分开的) + } else if (sFontSizeBtnsMap.containsKey(id)) { + findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.GONE); + mFontSizeId = sFontSizeBtnsMap.get(id); + mSharedPrefs.edit().putInt(PREFERENCE_FONT_SIZE, mFontSizeId).commit(); + findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE); + if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { getWorkingText(); switchToListMode(mWorkingNote.getContent()); - } else { // 否则,设置文本的外观为新的字体大小 + } else { mNoteEditor.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId)); } mFontSizeSelector.setVisibility(View.GONE); } } - //用户按下返回键时,清楚可见的设置状态并保存便签 + @Override public void onBackPressed() { if(clearSettingState()) { @@ -585,7 +461,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, saveNote(); super.onBackPressed(); } - //将还未被隐藏的选择器组件隐藏起来 + private boolean clearSettingState() { if (mNoteBgColorSelector.getVisibility() == View.VISIBLE) { mNoteBgColorSelector.setVisibility(View.GONE); @@ -596,79 +472,55 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return false; } - //当背景颜色发生更改时,更新相应的ui资源id + public void onBackgroundColorChanged() { findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( View.VISIBLE); mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId()); mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId()); } - /** - * @classname: NoteEditActivity - * @methodname onPrepareOptionsMenu - * @description:准备菜单项 - * @date: 2023/12/25 15:54 - * @author: Xia Yanbo - * @param:menu 当前Activity的菜单对象。 - * @return:如果已成功准备菜单,则返回true;否则返回false - */ + @Override public boolean onPrepareOptionsMenu(Menu menu) { - // 如果Activity即将被销毁,则直接返回true,不再继续准备菜单 if (isFinishing()) { return true; } - //将还未隐藏的选择器组件隐藏 clearSettingState(); - //清除已有的菜单的所有项 menu.clear(); - // 根据笔记所在的文件夹ID来决定使用哪个菜单布局 if (mWorkingNote.getFolderId() == Notes.ID_CALL_RECORD_FOLDER) { getMenuInflater().inflate(R.menu.call_note_edit, menu); } else { getMenuInflater().inflate(R.menu.note_edit, menu); } - // 根据笔记的文本模式来设置菜单项的标题 if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { menu.findItem(R.id.menu_list_mode).setTitle(R.string.menu_normal_mode); } else { menu.findItem(R.id.menu_list_mode).setTitle(R.string.menu_list_mode); } - // 根据笔记是否设置了闹钟提醒来决定是否显示某些菜单项 if (mWorkingNote.hasClockAlert()) { menu.findItem(R.id.menu_alert).setVisible(false); } else { menu.findItem(R.id.menu_delete_remind).setVisible(false); } - return true; } - /** - * @classname: NoteEditActivity - * @methodname onOptionsItemSelected - * @description:根据所选择的菜单项执行相应的功能 - * @date: 2023/12/25 16:22 - * @author: Xia Yanbo - * @param:item 当前便签内的菜单 - * @return:boolean 已经选中事件被成功处理返回true,否则返回false - */ + @Override public boolean onOptionsItemSelected(MenuItem item) { - //新建笔记 + if ( item.getItemId()==R.id.menu_new_note) { createNewNote(); } - //删除笔记 else if(item.getItemId()== R.id.menu_delete) { - //弹出确认删除的警示框 - AlertDialog.Builder builder = new AlertDialog.Builder(this); // 创建一个AlertDialog的构建器 - builder.setTitle(getString(R.string.alert_title_delete)); // 设置标题为“删除” - builder.setIcon(android.R.drawable.ic_dialog_alert); // 设置图标为警告图标 - builder.setMessage(getString(R.string.alert_message_delete_note)); // 设置消息为删除笔记的提示信息 - builder.setPositiveButton(android.R.string.ok, // 设置确认按钮 - new DialogInterface.OnClickListener() {//点击事件监听器 + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(getString(R.string.alert_title_delete)); + builder.setIcon(android.R.drawable.ic_dialog_alert); + builder.setMessage(getString(R.string.alert_message_delete_note)); + builder.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { deleteCurrentNote(); finish(); @@ -677,56 +529,41 @@ public class NoteEditActivity extends Activity implements OnClickListener, builder.setNegativeButton(android.R.string.cancel, null); builder.show(); } - //字体大小功能项 else if(item.getItemId()== R.id.menu_font_size) { - mFontSizeSelector.setVisibility(View.VISIBLE);//显示字体大小选择器 + mFontSizeSelector.setVisibility(View.VISIBLE); findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE); } - //列表模式 else if(item.getItemId()== R.id.menu_list_mode) { mWorkingNote.setCheckListMode(mWorkingNote.getCheckListMode() == 0 ? TextNote.MODE_CHECK_LIST : 0); } -// else if(item.getItemId()== R.id.menu_secret) -// { -// mWorkingNote.setSecretMode(); -// -// } -// else if(item.getItemId()== R.id.menu_quit_secret) -// { -// mWorkingNote.setSecretMode(); -// } - //分享 else if(item.getItemId()== R.id.menu_share) { - getWorkingText();//获取当前笔记的文本内容 - sendTo(this, mWorkingNote.getContent());//分享出去 + getWorkingText(); + sendTo(this, mWorkingNote.getContent()); } - //发送到桌面 else if(item.getItemId()== R.id.menu_send_to_desktop) { sendToDesktop(); } - //设置提醒 else if(item.getItemId()== R.id.menu_alert) { setReminder(); } - //删除提醒 else if(item.getItemId()== R.id.menu_delete_remind) { mWorkingNote.setAlertDate(0, false); } return true; } - //设置时间提醒 + private void setReminder() { DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis()); - d.setOnDateTimeSetListener(new OnDateTimeSetListener() {//监听设置的时间 + d.setOnDateTimeSetListener(new OnDateTimeSetListener() { public void OnDateTimeSet(AlertDialog dialog, long date) { - mWorkingNote.setAlertDate(date , true);//设置提醒的日期时间 + mWorkingNote.setAlertDate(date , true); } }); d.show(); @@ -735,83 +572,69 @@ public class NoteEditActivity extends Activity implements OnClickListener, /** * Share note to apps that support {@link Intent#ACTION_SEND} action * and {@text/plain} type - * 将便签发送到支持的app应用 */ private void sendTo(Context context, String info) { - Intent intent = new Intent(Intent.ACTION_SEND);//意图为发送 - intent.putExtra(Intent.EXTRA_TEXT, info);//附加要发送的信息到intent - intent.setType("text/plain");//设定传输的类型 - context.startActivity(intent);//根据意图开始发送信息 + 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();//保存当前便签 + saveNote(); // For safety, start a new NoteEditActivity - finish();//销毁资源,关闭当前便签 + finish(); Intent intent = new Intent(this, NoteEditActivity.class); - intent.setAction(Intent.ACTION_INSERT_OR_EDIT);//设置活动为编辑 - intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mWorkingNote.getFolderId());//附加包和便签的id + intent.setAction(Intent.ACTION_INSERT_OR_EDIT); + intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mWorkingNote.getFolderId()); startActivity(intent); } - /** - * @classname: NoteEditActivity - * @methodname deleteCurrentNote - * @description:删除当前便签 - * @date: 2023/12/25 21:28 - * @author: Xia Yanbo - */ + private void deleteCurrentNote() { - if (mWorkingNote.existInDatabase()) {//检查笔记是否在数据库里 - HashSet ids = new HashSet();// 创建一个空的HashSet用于存储笔记ID + if (mWorkingNote.existInDatabase()) { + HashSet ids = new HashSet(); long id = mWorkingNote.getNoteId(); - if (id != Notes.ID_ROOT_FOLDER) {// 如果笔记ID不是根文件夹ID,则将其添加到HashSet中 + if (id != Notes.ID_ROOT_FOLDER) { ids.add(id); - } else {// 如果笔记ID是根文件夹ID,则打印错误日志,因为这不该发生 + } else { Log.d(TAG, "Wrong note id, should not happen"); } - if (!isSyncMode()) {// 如果不是同步模式,则执行删除操作 + if (!isSyncMode()) { if (!DataUtils.batchDeleteNotes(getContentResolver(), ids)) { Log.e(TAG, "Delete Note error"); } - } else {//如果是同步模式则将笔记移动到垃圾箱文件夹,如果失败则打印错误日志 + } else { if (!DataUtils.batchMoveToFolder(getContentResolver(), ids, Notes.ID_TRASH_FOLER)) { Log.e(TAG, "Move notes to trash folder error, should not happens"); } } } - mWorkingNote.markDeleted(true);//标记当前笔记为已删除 + mWorkingNote.markDeleted(true); } - //判断是否处于同步模式 + private boolean isSyncMode() { - //只需判断当前是否有账户名 return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0; } - /** - * @classname: NoteEditActivity - * @methodname onClockAlertChanged - * @description: - * @date: 2023/12/25 21:34 - * @author: Xia Yanbo - */ + 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();//不在数据库先保存 + saveNote(); } if (mWorkingNote.getNoteId() > 0) { Intent intent = new Intent(this, AlarmReceiver.class); intent.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mWorkingNote.getNoteId())); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); - AlarmManager alarmManager = ((AlarmManager) getSystemService(ALARM_SERVICE));//获取系统的闹钟服务 + AlarmManager alarmManager = ((AlarmManager) getSystemService(ALARM_SERVICE)); showAlertHeader(); - if(!set) {//取消设置闹钟 + if(!set) { alarmManager.cancel(pendingIntent); - } else {//设置闹钟 + } else { alarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent); } } else { @@ -821,34 +644,26 @@ public class NoteEditActivity extends Activity implements OnClickListener, * should input something */ Log.e(TAG, "Clock alert setting error"); - showToast(R.string.error_note_empty_for_clock);//显示toast消息,用于提醒用户输入 + showToast(R.string.error_note_empty_for_clock); } } - //更新当前的控件 + public void onWidgetChanged() { updateWidget(); } - /** - * @classname: NoteEditActivity - * @methodname onEditTextDelete - * @description:删除正收编辑的文本 - * @date: 2023/12/25 21:41 - * @author: Xia Yanbo - * @param:text待移除的文本 - * @param:index要移除的子项的索引 - */ + public void onEditTextDelete(int index, String text) { - int childCount = mEditTextList.getChildCount();//获取子项的数量 + int childCount = mEditTextList.getChildCount(); if (childCount == 1) { return; } - // 将NoteEditText的索引更新为当前索引减1 + for (int i = index + 1; i < childCount; i++) { ((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text)) .setIndex(i - 1); } - mEditTextList.removeViewAt(index);//移除指定索引号的子项 + mEditTextList.removeViewAt(index); NoteEditText edit = null; if(index == 0) { edit = (NoteEditText) mEditTextList.getChildAt(0).findViewById( @@ -862,44 +677,43 @@ public class NoteEditActivity extends Activity implements OnClickListener, edit.requestFocus(); edit.setSelection(length); } - //文本输入换行并更新文本存储列表的索引值 + 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");//超出编辑列表的边界 + 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); - edit.requestFocus();//设置焦点 + edit.requestFocus(); edit.setSelection(0); - //文本编辑视图列表中的每一项设置索引值 for (int i = index + 1; i < mEditTextList.getChildCount(); i++) { ((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text)) .setIndex(i); } } - //切换到任务清单模式 + private void switchToListMode(String text) { mEditTextList.removeAllViews(); String[] items = text.split("\n"); int index = 0; for (String item : items) { if(!TextUtils.isEmpty(item)) { - mEditTextList.addView(getListItem(item, index));//添加列表项(标记:实现的关键步骤addView,getlistitem) + mEditTextList.addView(getListItem(item, index)); index++; } } mEditTextList.addView(getListItem("", index)); mEditTextList.getChildAt(index).findViewById(R.id.et_edit_text).requestFocus(); - mNoteEditor.setVisibility(View.GONE);//用于一般模式的编辑组件隐藏 - mEditTextList.setVisibility(View.VISIBLE);//用于任务清单模式的编辑组件显示 + 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)) { @@ -907,7 +721,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, Matcher m = mPattern.matcher(fullText); int start = 0; while (m.find(start)) { - spannable.setSpan(//使用资源中的颜色(标记:可参考用作设计颜色) + spannable.setSpan( new BackgroundColorSpan(this.getResources().getColor( R.color.user_query_highlight)), m.start(), m.end(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); @@ -916,33 +730,14 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return spannable; } - /** - * @classname: NoteEditActivity - * @methodname getListItem - * @description:根据给定的数据和索引值创建一个列表项视图 - * @date: 2023/12/26 23:52 - * @author: Xia Yanbo - * @param:item数据 - * @param:index索引值 - * @return:view 新创建的列表项视图 - */ + private View getListItem(String item, int index) { - // 从当前上下文中加载NoteEditList_item布局文件,并返回一个View对象。 View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null); - - // 获取NoteEditTextView组件 final NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text); - - // 设置文本的外观样式,使用传入的字体大小ID作为参数。 - edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));//标记,能改动文字大小的关键所在 - - // 获取CheckBox组件 + edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId)); CheckBox cb = ((CheckBox) view.findViewById(R.id.cb_edit_item)); - - // 设置CheckBox的选中状态监听器 cb.setOnCheckedChangeListener(new OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - // 如果CheckBox被选中,则设置文本的绘制标志为删除线;否则设置为抗锯齿和文本对齐。 if (isChecked) { edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); } else { @@ -951,7 +746,6 @@ public class NoteEditActivity extends Activity implements OnClickListener, } }); - // 根据item的开头判断是否为已选或未选,并设置相应的CheckBox状态和文本绘制样式。 if (item.startsWith(TAG_CHECKED)) { cb.setChecked(true); edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); @@ -962,29 +756,24 @@ public class NoteEditActivity extends Activity implements OnClickListener, item = item.substring(TAG_UNCHECKED.length(), item.length()).trim(); } - // 设置NoteEditTextView的监听器为当前对象(this),以便在外部进行监听和处理。 edit.setOnTextViewChangeListener(this); - // 设置NoteEditTextView的索引值。 edit.setIndex(index); - // 为NoteEditTextView设置带有高亮显示的全文文本。使用传入的用户查询作为参数。 edit.setText(getHighlightQueryResult(item, mUserQuery)); - // 返回创建的列表项视图。 return view; } - //文本变化时进行复选框的设置 + public void onTextChange(int index, boolean hasText) { if (index >= mEditTextList.getChildCount()) { Log.e(TAG, "Wrong index, should not happen"); return; } - //设置复选框的出现与否 if(hasText) { mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.VISIBLE); } else { mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.GONE); } } - //进出任务清单模式时复选框等组件的设置 + public void onCheckListModeChanged(int oldMode, int newMode) { if (newMode == TextNote.MODE_CHECK_LIST) { switchToListMode(mNoteEditor.getText().toString()); @@ -996,17 +785,9 @@ public class NoteEditActivity extends Activity implements OnClickListener, mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery)); mEditTextList.setVisibility(View.GONE); mNoteEditor.setVisibility(View.VISIBLE); - convertToImage(); } } - /** - * @classname: NoteEditActivity - * @methodname getWorkingText - * @description:对选中的文本项设置值为完成 - * @date: 2023/12/27 0:03 - * @author: Xia Yanbo - * @return:boolean表示文本项被设置成的完成状态 - */ + private boolean getWorkingText() { boolean hasChecked = false; if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { @@ -1025,11 +806,11 @@ public class NoteEditActivity extends Activity implements OnClickListener, } mWorkingNote.setWorkingText(sb.toString()); } else { - mWorkingNote.setWorkingText(mNoteEditor.getText().toString());//不做标记值的更改 + mWorkingNote.setWorkingText(mNoteEditor.getText().toString()); } return hasChecked; } - //保存便签 + private boolean saveNote() { getWorkingText(); boolean saved = mWorkingNote.saveNote(); @@ -1045,7 +826,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, } return saved; } - //保存便签并发送到桌面 + private void sendToDesktop() { /** * Before send message to home, we should make sure that current @@ -1080,14 +861,14 @@ public class NoteEditActivity extends Activity implements OnClickListener, 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; } - //消息传递 + private void showToast(int resId) { showToast(resId, Toast.LENGTH_SHORT); } @@ -1095,174 +876,4 @@ public class NoteEditActivity extends Activity implements OnClickListener, private void showToast(int resId, int duration) { Toast.makeText(this, resId, duration).show(); } - //路径字符串格式 转换为 图片image格式 - private void convertToImage() { - NoteEditText noteEditText = (NoteEditText) findViewById(R.id.note_edit_view); //获取当前的edit - Editable editable = noteEditText.getText();//1.获取text - String noteText = editable.toString(); //2.将note内容转换为字符串 - int length = editable.length(); //内容的长度 - //3.截取img片段 [local]+uri+[local],提取uri - for(int i = 0; i < length; i++) { - for(int j = i; j < length; j++) { - String img_fragment = noteText.substring(i, j+1); //img_fragment:关于图片路径的片段 - if(img_fragment.length() > 15 && img_fragment.endsWith("[/local]") && img_fragment.startsWith("[local]")){ - int limit = 7; //[local]为7个字符 - //[local][/local]共15个字符,剩下的为真正的path长度 - int len = img_fragment.length()-15; - //从[local]之后的len个字符就是path - String path = img_fragment.substring(limit,limit+len);//获取到了图片路径 - Bitmap bitmap = null; - Log.d(TAG, "图片的路径是:"+path); - try { - bitmap = BitmapFactory.decodeFile(path);//将图片路径解码为图片格式 - } catch (Exception e) { - e.printStackTrace(); - } - if(bitmap!=null){ //若图片存在 - Log.d(TAG, "图片不为null"); - ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap); - //4.创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像 - String ss = "[local]" + path + "[/local]"; - SpannableString spannableString = new SpannableString(ss); - //5.将指定的标记对象附加到文本的开始...结束范围 - spannableString.setSpan(imageSpan, 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - Log.d(TAG, "Create spannable string success!"); - Editable edit_text = noteEditText.getEditableText(); - edit_text.delete(i,i+len+15); //6.删掉图片路径的文字 - edit_text.insert(i, spannableString); //7.在路径的起始位置插入图片 - } - } - } - } - } - - //重写onActivityResult()来处理返回的数据 - protected void onActivityResult(int requestCode, int resultCode, Intent intent) { - super.onActivityResult(requestCode, resultCode, intent); - ContentResolver resolver = getContentResolver(); - switch (requestCode) { - case PHOTO_REQUEST: - Uri originalUri = intent.getData(); //1.获得图片的真实路径 - Bitmap bitmap = null; - try { - bitmap = BitmapFactory.decodeStream(resolver.openInputStream(originalUri));//2.解码图片 - } catch (FileNotFoundException e) { - Log.d(TAG, "onActivityResult: get file_exception"); - e.printStackTrace(); - } - - if(bitmap != null){ - //3.根据Bitmap对象创建ImageSpan对象 - Log.d(TAG, "onActivityResult: bitmap is not null"); - ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap); - String path = getPath(this,originalUri); - //4.使用[local][/local]将path括起来,用于之后方便识别图片路径在note中的位置 - String img_fragment= "[local]" + path + "[/local]"; - //创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像 - SpannableString spannableString = new SpannableString(img_fragment); - spannableString.setSpan(imageSpan, 0, img_fragment.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - //5.将选择的图片追加到EditText中光标所在位置 - NoteEditText e = (NoteEditText) findViewById(R.id.note_edit_view); - int index = e.getSelectionStart(); //获取光标所在位置 - Log.d(TAG, "Index是: " + index); - Editable edit_text = e.getEditableText(); - edit_text.insert(index, spannableString); //将图片插入到光标所在位置 - - mWorkingNote.mContent = e.getText().toString(); - //6.把改动提交到数据库中,两个数据库表都要改的 - ContentResolver contentResolver = getContentResolver(); - ContentValues contentValues = new ContentValues(); - final long id = mWorkingNote.getNoteId(); - contentValues.put("snippet",mWorkingNote.mContent); - contentResolver.update(Uri.parse("content://micode_notes/note"), contentValues,"_id=?",new String[]{""+id}); - ContentValues contentValues1 = new ContentValues(); - contentValues1.put("content",mWorkingNote.mContent); - contentResolver.update(Uri.parse("content://micode_notes/data"), contentValues1,"mime_type=? and note_id=?", new String[]{"vnd.android.cursor.item/text_note",""+id}); - - }else{ - Toast.makeText(NoteEditActivity.this, "获取图片失败", Toast.LENGTH_SHORT).show(); - } - break; - default: - break; - } - } - - //获取文件的real path - public String getPath(final Context context, final Uri uri) { - - final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - - // DocumentProvider - if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { - // ExternalStorageProvider -// if (isExternalStorageDocument(uri)) { -// final String docId = DocumentsContract.getDocumentId(uri); -// final String[] split = docId.split(":"); -// final String type = split[0]; -// -// if ("primary".equalsIgnoreCase(type)) { -// return Environment.getExternalStorageDirectory() + "/" + split[1]; -// } -// } -// // DownloadsProvider -// else if (isDownloadsDocument(uri)) { -// final String id = DocumentsContract.getDocumentId(uri); -// final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); -// return getDataColumn(context, contentUri, null, null); -// } - // MediaProvider -// else - if (isMediaDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - Uri contentUri = null; - if ("image".equals(type)) { - contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } - - final String selection = "_id=?"; - final String[] selectionArgs = new String[]{split[1]}; - - return getDataColumn(context, contentUri, selection, selectionArgs); - } - } - // Media - else if ("content".equalsIgnoreCase(uri.getScheme())) { - return getDataColumn(context, uri, null, null); - } - // File - else if ("file".equalsIgnoreCase(uri.getScheme())) { - return uri.getPath(); - } - return null; - } - - //获取数据列_获取此 Uri 的数据列的值。这对MediaStore Uris 和其他基于文件的 ContentProvider。 - public String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { - - Cursor cursor = null; - final String column = "_data"; - final String[] projection = {column}; - - try { - cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); - if (cursor != null && cursor.moveToFirst()) { - final int column_index = cursor.getColumnIndexOrThrow(column); - return cursor.getString(column_index); - } - } finally { - if (cursor != null) - cursor.close(); - } - return null; - } - - //是否为媒体文件 - public boolean isMediaDocument(Uri uri) { - return "com.android.providers.media.documents".equals(uri.getAuthority()); - } - } diff --git a/src/main/java/net/micode/notes/ui/NoteEditText.java b/src/main/java/net/micode/notes/ui/NoteEditText.java index 34fc9dd..556af3f 100644 --- a/src/main/java/net/micode/notes/ui/NoteEditText.java +++ b/src/main/java/net/micode/notes/ui/NoteEditText.java @@ -1,4 +1,4 @@ -/* +/* 批过了 * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,23 +36,16 @@ import net.micode.notes.R; import java.util.HashMap; import java.util.Map; -/** - * @classname: NoteEditText - * @description:NoteEditText继承了 EditText父类 - * 负责开启监听以完成文本的读取,并做出相应的处理动作 - * 同时还负责上下文菜单的创建 - * @date: 2023/12/24 9:22 - * @author: Xia Yanbo -*/ + public class NoteEditText extends EditText { - private static final String TAG = "NoteEditText";//标签,分类接收特定信息 - private int mIndex;//声明文本的索引 + 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); @@ -62,65 +55,53 @@ public class NoteEditText extends EditText { /** * Call by the {@link NoteEditActivity} to delete or add edit text - * 可以用作往整个文本里添加以及删除文本,会被NoteEditActivity时常调用 */ public interface OnTextViewChangeListener { /** * Delete current edit text when {@link KeyEvent#KEYCODE_DEL} happens * and the text is null - * 当按下delete时删除编辑的文字 */ void onEditTextDelete(int index, String text); /** * Add edit text after current edit text when {@link KeyEvent#KEYCODE_ENTER} * happen - * 当按下enter时添加编辑的文本到文本中 */ void onEditTextEnter(int index, String text); /** * Hide or show item option when text change - * 当文字发生变化时显示或者隐藏起设置 */ void onTextChange(int index, boolean hasText); } - //声明文本视图变化的监听器 + private OnTextViewChangeListener mOnTextViewChangeListener; - //实例化NoteEditText对象, + public NoteEditText(Context context) { super(context, null); mIndex = 0; } - //为本本编辑设置一个索引 + public void setIndex(int index) { mIndex = index; } - //直接调用父类,定义好文本视图变化的监听器 + public void setOnTextViewChangeListener(OnTextViewChangeListener listener) { mOnTextViewChangeListener = listener; } - //NoteEditText的构造函数,通过文本编辑风格的参数集实例化 + public NoteEditText(Context context, AttributeSet attrs) { super(context, attrs, android.R.attr.editTextStyle); } - //NoteEditText的构造函数,通过文本编辑风格的参数集实例化,支持用户自定义风格 + public NoteEditText(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle);//允许自定义风格 + super(context, attrs, defStyle); // TODO Auto-generated constructor stub } - /** - * @classname: NoteEditText - * @methodname onTouchEvent - * @description:根据得到的用户采取的动作(事件)类型进行相应的光标的设置 - * @date: 2023/12/24 10:05 - * @author: Xia Yanbo - * @param:event 具体的动作动作事件 - * @return:boolean 表示是否成功 - */ + @Override public boolean onTouchEvent(MotionEvent event) { - switch (event.getAction()) {//对动作事件进行分类的判别 + switch (event.getAction()) { case MotionEvent.ACTION_DOWN: int x = (int) event.getX(); @@ -131,24 +112,15 @@ public class NoteEditText extends EditText { y += getScrollY(); Layout layout = getLayout(); - int line = layout.getLineForVertical(y);//直接获取行数 - int off = layout.getOffsetForHorizontal(line, x);//从边界起数获得偏移 + int line = layout.getLineForVertical(y); + int off = layout.getOffsetForHorizontal(line, x); Selection.setSelection(getText(), off); break; } - return super.onTouchEvent(event);//再调用父类的方法进行后续的处理 + return super.onTouchEvent(event); } - /** - * @classname: NoteEditText - * @methodname onKeyDown - * @description:监听键盘按键按下 - * @date: 2023/12/24 10:15 - * @author: Xia Yanbo - * @param:keyCode 按键的编码值 - * @param:event 按键的具体事件 - * @return:boolean 表示判断执行的过程是否顺利 - */ + @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { @@ -165,16 +137,7 @@ public class NoteEditText extends EditText { } return super.onKeyDown(keyCode, event); } - /** - * @classname: NoteEditText - * @methodname onKeyUp - * @description:监听键盘按键抬起 - * @date: 2023/12/24 10:15 - * @author: Xia Yanbo - * @param:keyCode 按键的编码值 - * @param:event 按键的具体事件 - * @return:boolean 表示判断执行的过程是否顺利 - */ + @Override public boolean onKeyUp(int keyCode, KeyEvent event) { switch(keyCode) { @@ -203,20 +166,11 @@ public class NoteEditText extends EditText { } return super.onKeyUp(keyCode, event); } - /** - * @classname: NoteEditText - * @methodname onFocusChanged - * @description:对应当前视图的焦点改变 - * @date: 2023/12/24 10:25 - * @author: Xia Yanbo - * @param:focused 焦点改变或者还未改变 - * @param:direction 改变方向? - * @param:reviouslyFocusedRect 上一个焦点所关注的视图 - */ + @Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { if (mOnTextViewChangeListener != null) { - if (!focused && TextUtils.isEmpty(getText())) {//当没有输入,关注的视图也发生改变,设置隐藏 + if (!focused && TextUtils.isEmpty(getText())) { mOnTextViewChangeListener.onTextChange(mIndex, false); } else { mOnTextViewChangeListener.onTextChange(mIndex, true); @@ -224,27 +178,19 @@ public class NoteEditText extends EditText { } super.onFocusChanged(focused, direction, previouslyFocusedRect); } - /** - * @classname: NoteEditText - * @methodname onCreateContextMenu - * @description:创建文本的上下文菜单 - * @date: 2023/12/24 10:34 - * @author: Xia Yanbo - * @param:contextMenu 现有的上下文菜单 - */ + @Override protected void onCreateContextMenu(ContextMenu menu) { - if (getText() instanceof Spanned) {//检查文本的类型 Spanned是一个接口 - int selStart = getSelectionStart();//所选择文本的开始位置 - int selEnd = getSelectionEnd();//所选择文本的结束位置 - //确定选择开始的较小值和较大值,方便直接做差 + if (getText() instanceof Spanned) { + int selStart = getSelectionStart(); + int selEnd = getSelectionEnd(); + int min = Math.min(selStart, selEnd); int max = Math.max(selStart, selEnd); - //获取选择的文本范围内获取所有的 URLSpan 对象。URLSpan 是用于表示文本中的链接的。 - final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class);//获取范围 + + final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class); if (urls.length == 1) { int defaultResId = 0; - //根据URL获取资源 for(String schema: sSchemaActionResMap.keySet()) { if(urls[0].getURL().indexOf(schema) >= 0) { defaultResId = sSchemaActionResMap.get(schema); @@ -255,10 +201,9 @@ public class NoteEditText extends EditText { if (defaultResId == 0) { defaultResId = R.string.note_link_other; } - //添加菜单项 + menu.add(0, 0, 0, defaultResId).setOnMenuItemClickListener( new OnMenuItemClickListener() { - //设置监听器,放菜单项被点击,触发链接 public boolean onMenuItemClick(MenuItem item) { // goto a new intent urls[0].onClick(NoteEditText.this); @@ -267,6 +212,6 @@ public class NoteEditText extends EditText { }); } } - super.onCreateContextMenu(menu);//调用父类方法 + super.onCreateContextMenu(menu); } } diff --git a/src/main/res/layout/note_edit.xml b/src/main/res/layout/note_edit.xml index eca025e..10b2aa7 100644 --- a/src/main/res/layout/note_edit.xml +++ b/src/main/res/layout/note_edit.xml @@ -395,15 +395,6 @@ android:layout_marginRight="6dip" android:layout_marginBottom="-7dip" android:src="@drawable/selected" /> - - diff --git a/src/main/res/menu/sub_folder.xml b/src/main/res/menu/sub_folder.xml index 41fe907..b00de26 100644 --- a/src/main/res/menu/sub_folder.xml +++ b/src/main/res/menu/sub_folder.xml @@ -21,11 +21,4 @@ - - - \ No newline at end of file diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 214a5eb..09f75ed 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -71,8 +71,6 @@ 确认要删除该条便签吗? 确认删除文件夹及所包含的便签吗? 已将所选 %1$d 条便签移到 %2$s 文件夹 - 私密模式 - 退出私密模式 SD卡被占用,不能操作 导出文本时发生错误,请检查SD卡 diff --git a/src/main/res/values/colors.xml b/src/main/res/values/colors.xml index 123ffbf..2496c0c 100644 --- a/src/main/res/values/colors.xml +++ b/src/main/res/values/colors.xml @@ -17,4 +17,9 @@ #335b5b5b + #FF039BE5 + #FF01579B + #FF40C4FF + #FF00B0FF + #66000000 diff --git a/src/main/res/values/styles.xml b/src/main/res/values/styles.xml index ad0d90d..402ff1f 100644 --- a/src/main/res/values/styles.xml +++ b/src/main/res/values/styles.xml @@ -16,18 +16,22 @@ --> + + + + @@ -63,7 +67,16 @@ + + + + \ No newline at end of file