Compare commits

...

18 Commits

Author SHA1 Message Date
王润泽 ee9e7d0bb3 Merge branch 'wangrunze_branch' of https://bdgit.educoder.net/mth9uq3ve/xiaomi_mini
11 months ago
王润泽 de9efc5179 活动
11 months ago
mth9uq3ve 0a3a2ebde1 精读批注第二次提交
11 months ago
夏彦博 a8b8243502 批注了NoteEditActivity
11 months ago
mth9uq3ve adfcb1ae14 精读批注第一次上传
11 months ago
夏彦博 127e07ab58 批注了NoteEditText和GTaskASyncTask两个类
11 months ago
夏彦博 d9b9dde803 标准批注了exception两个类
11 months ago
夏彦博 ee0e553b4f 增加了批注的行数的统计表
12 months ago
夏彦博 60f54c08db gtask包中的data包批注完成
12 months ago
夏彦博 b9e5d499ac 批注gtask包中的data里面的4个类
12 months ago
mth9uq3ve 9928cf3ca5 提交完整的泛读报告
12 months ago
夏彦博 7b2964bf2d 更新包图,并统一文章格式,排版
12 months ago
王润泽 3504c8ad29 功能与类的关系
12 months ago
王润泽 e74122b424 Merge branch 'develop' of https://bdgit.educoder.net/mth9uq3ve/xiaomi_mini
12 months ago
夏彦博 5c0ee8bd93 修复了data包的类图由于内部类导致的一点问题
12 months ago
夏彦博 6671235f86 完善了widget,gtask类图,以及包图更新
12 months ago
mth9uq3ve ef14e3cb62 Merge pull request 'model类图' (#1) from wangrunze_branch into develop
1 year ago
夏彦博 ccadbd921b 创建当前版本
1 year ago

@ -0,0 +1,3 @@
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Android API 33, extension level 3 Platform" project-jdk-type="Android SDK" />
</project>

Binary file not shown.

@ -22,31 +22,44 @@ import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Data;
import android.telephony.PhoneNumberUtils;
import android.util.Log;
import java.util.HashMap;
public class Contact {//定义一个Contact类类别标签为Contact包含一个用于存储用户信息的HashMap
private static HashMap<String, String> sContactCache;
private static final String TAG = "Contact";
//定义静态常量,用于查询指定联系人
// 该代码是一个名为Contact的类用于获取联系人信息。
//代码中定义了一个静态的HashMap变量sContactCache用于缓存联系人信息。sContactCache的键是电话号码值是联系人姓名。
//定义了一个字符串常量CALLER_ID_SELECTION用于查询联系人信息的条件。该条件是通过拼接字符串而得到的包含了查询电话号码相等、数据类型为电话号码、联系人ID在指定范围内等条件。
//代码中定义了一个静态方法getContact用于根据电话号码获取联系人姓名。
public class Contact {
private static HashMap<String, String> 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 = '+')";
//定义一个静态方法getContact可以通过Contact对象以及电话号码查询联系人。
+ " 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<String, String>();
}
if(sContactCache.containsKey(phoneNumber)) {//如果已经包含电话号码作为关键字对应的用户
return sContactCache.get(phoneNumber);//直接返回用户的名字get返回名字
// 查找HashMap中是否已有phoneNumber信息
if (sContactCache.containsKey(phoneNumber)) {
return sContactCache.get(phoneNumber);//直接根据键值(电话号码)找到姓名
}
String selection = CALLER_ID_SELECTION.replace("+",
PhoneNumberUtils.toCallerIDMinMatch(phoneNumber));
PhoneNumberUtils.toCallerIDMinMatch(phoneNumber));//最小匹配原则查找电话号码
// 查找数据库中phoneNumber的信息
Cursor cursor = context.getContentResolver().query(
Data.CONTENT_URI,
new String[] { Phone.DISPLAY_NAME },
@ -54,10 +67,12 @@ public class Contact {//定义一个Contact类类别标签为Contact包含
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());
@ -66,7 +81,8 @@ public class Contact {//定义一个Contact类类别标签为Contact包含
cursor.close();
}
} else {
Log.d(TAG, "No contact matched with number:" + phoneNumber);
// 未找到相关信息
Log.d(TAG, "No contact matched with number:" + phoneNumber);//给出反馈信息
return null;
}
}

@ -24,8 +24,8 @@ import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONException;
import org.json.JSONObject;
public class MetaData extends Task {
//主要是定义用于处理元数据
public class MetaData extends Task {//继承task是task的子类
private final static String TAG = MetaData.class.getSimpleName();
private String mRelatedGid = null;
@ -34,7 +34,7 @@ public class MetaData extends 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 {
@Override
public boolean isWorthSaving() {
return getNotes() != null;
}
}//用于判断数据是否值得保存
@Override
public void setContentByRemoteJSON(JSONObject js) {
public void setContentByRemoteJSON(JSONObject js) {//用远程的json设置内容基础操作元
super.setContentByRemoteJSON(js);
if (getNotes() != null) {
try {
@ -64,9 +64,9 @@ public class MetaData extends 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");
throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called");//抛出了IllegalAccessError异常表明它不应该被直接调用
}
@Override

@ -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,6 +38,7 @@ public abstract class Node {
public static final int SYNC_ACTION_UPDATE_CONFLICT = 7;
public static final int SYNC_ACTION_ERROR = 8;
//为不同的同步类型添加调用编号
private String mGid;
@ -45,7 +46,7 @@ public abstract class Node {
private long mLastModified;
private boolean mDeleted;
private boolean mDeleted;//设置基础值,定义获取参数的方法
public Node() {
mGid = null;
@ -64,9 +65,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;
}
@ -82,7 +83,7 @@ public abstract class Node {
this.mDeleted = deleted;
}
public String getGid() {
public String getGid() {//this保证指向的还是当前的对象
return this.mGid;
}

@ -71,9 +71,9 @@ public class SqlData {
private ContentValues mDiffDataValues;
public SqlData(Context context) {
public SqlData(Context context) {//初始化对象,用于存储数据
mContentResolver = context.getContentResolver();
mIsCreate = true;
mIsCreate = true;//一类型的变量为true
mDataId = INVALID_ID;
mDataMimeType = DataConstants.NOTE;
mDataContent = "";
@ -82,14 +82,14 @@ public class SqlData {
mDiffDataValues = new ContentValues();
}
public SqlData(Context context, Cursor c) {
public SqlData(Context context, Cursor c) {//同样是存储数据另外定义支持冲cursor读入
mContentResolver = context.getContentResolver();
mIsCreate = false;
mIsCreate = false;//二类型的变量为false
loadFromCursor(c);
mDiffDataValues = new ContentValues();
}
private void loadFromCursor(Cursor c) {
private void loadFromCursor(Cursor c) {//上面用到的从cursor读取的函数从存储的各个列获取数据
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(JSONObject js) throws JSONException {
long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;
if (mIsCreate || mDataId != dataId) {
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产生的数据元可通过它完成更新
mDiffDataValues.put(DataColumns.ID, dataId);
}
mDataId = dataId;
@ -131,7 +131,7 @@ public class SqlData {
}
public JSONObject getContent() throws JSONException {
if (mIsCreate) {
if (mIsCreate) {//同样的只有通过cursor产生的数据单元可通过这个函数获取数据
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) {
if (!validateVersion) { // 不验证版本的情况下直接使用ContentResolver更新指定ID的数据
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null);
} else {
} else { // 需要验证版本的情况下使用ContentResolver进行条件更新操作
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues,
" ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE

@ -122,7 +122,7 @@ public class SqlNote {
private ArrayList<SqlData> 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);
loadFromCursor(c);//从cursor中直接获取变量值
mDataList = new ArrayList<SqlData>();
if (mType == Notes.TYPE_NOTE)
loadDataContent();
mDiffNoteValues = new ContentValues();
}
public SqlNote(Context context, long id) {
public SqlNote(Context context, long id) {//根据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) {
private void loadFromCursor(Cursor c) {//直接使用get获得变量值
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);
mDataList.add(data);//向Datalist中加入读取到的数据
}
} else {
Log.w(TAG, "loadDataContent: cursor = null");
@ -226,7 +226,8 @@ 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) {
@ -359,7 +360,7 @@ public class SqlNote {
return true;
}
public JSONObject getContent() {
public JSONObject getContent() {//直接读取的方式将所需的数据读到对应变量
try {
JSONObject js = new JSONObject();
@ -412,6 +413,7 @@ public class SqlNote {
mDiffNoteValues.put(NoteColumns.PARENT_ID, id);
}
//定义一些简单的获取取值的方法
public void setGtaskId(String gid) {
mDiffNoteValues.put(NoteColumns.GTASK_ID, gid);
}
@ -440,7 +442,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);

@ -32,7 +32,7 @@ import org.json.JSONException;
import org.json.JSONObject;
public class Task extends Node {
public class Task extends Node {//继承Node类的属性
private static final String TAG = Task.class.getSimpleName();
private boolean mCompleted;
@ -54,7 +54,7 @@ public class Task extends 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 {
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 {
// 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 {
return js;
}
public void setContentByRemoteJSON(JSONObject js) {
public void setContentByRemoteJSON(JSONObject js) {//通过远端的json设置内容的值
if (js != null) {
try {
// id
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {//如果值已经被json对象所具备则直接进行设置
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
}
@ -175,7 +175,7 @@ public class Task extends Node {
}
}
public void setContentByLocalJSON(JSONObject js) {
public void setContentByLocalJSON(JSONObject js) {//通过本地的json文件来设置内容
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 {
}
}
public JSONObject getLocalJSONFromContent() {
public JSONObject getLocalJSONFromContent() {//通过本地的内容生成json文件
String name = getName();
try {
if (mMetaInfo == null) {
@ -216,7 +216,7 @@ public class Task extends 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 {
} 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 {
}
}
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 {
return SYNC_ACTION_ERROR;
}
public boolean isWorthSaving() {
public boolean isWorthSaving() {//只要有信息就认为是值得保存的返回true
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;

@ -30,17 +30,17 @@ import org.json.JSONObject;
import java.util.ArrayList;
public class TaskList extends Node {
public class TaskList extends Node {//同Task一样继承了Node
private static final String TAG = TaskList.class.getSimpleName();
private int mIndex;
private ArrayList<Task> mChildren;
private ArrayList<Task> mChildren;//内部含有一个Task的列是任务的序列
public TaskList() {
super();
mChildren = new ArrayList<Task>();
mIndex = 1;
mIndex = 1;//初始化
}
public JSONObject getCreateAction(int actionId) {
@ -74,7 +74,7 @@ public class TaskList extends Node {
return js;
}
public JSONObject getUpdateAction(int actionId) {
public JSONObject getUpdateAction(int actionId) {//更新行动与Task中定义的基本一样
JSONObject js = new JSONObject();
try {
@ -104,7 +104,7 @@ public class TaskList extends 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 {
}
}
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 {
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 {
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 {
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 {
return (removeChildTask(task) && addChildTask(task, index));
}
public Task findChildTaskByGid(String gid) {
public Task findChildTaskByGid(String gid) {//通过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 {
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 {
public Task getChilTaskByGid(String gid) {
for (Task task : mChildren) {
if (task.getGid().equals(gid))
if (task.getGid().equals(gid))//找到一个gid相符的即为所要的任务
return task;
}
return null;

@ -15,19 +15,28 @@
*/
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);
}
}

@ -14,19 +14,30 @@
* limitations under the License.
*/
package net.micode.notes.gtask.exception;
package net.micode.notes.gtask.exception;//调用完成异常处理
/**
* @method: NetworkFailureException
* @description:NetworkFailureException Exception
*
* //定义了私有参数serialVersionUID是序列化用于验证版本一致性
* @date: 11:07
* @author: Xia Yanbo
* @param:
* @param:
* @param:
*/
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);
}

@ -29,10 +29,21 @@ 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<Void, String, Integer> {
private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;
private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;//序列化,用于验证版本
//声明定义一个接口OnCompleteListener实现放在后面
public interface OnCompleteListener {
void onComplete();
}
@ -44,7 +55,16 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
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;
@ -52,22 +72,42 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
.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:tickerIdID
* @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,
@ -79,24 +119,43 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
}
// 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) {
showNotification(R.string.ticker_syncing, progress[0]);//显示正在进行同步操作的通知
if (mContext instanceof GTaskSyncService) {//检查是否是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) {
@ -111,7 +170,7 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
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() {

@ -39,35 +39,50 @@ import net.micode.notes.tool.DataUtils;
import java.io.IOException;
/**
* @classname: AlarmAlertActivity
* @description:
* @date: 2023/12/28 11:18
* @author: wangrunze
*/
public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener {
private long mNoteId;
private String mSnippet;
private long mNoteId;//文本在数据库存储中的ID号
private String mSnippet;//闹钟提示时出现的文本片段
private static final int SNIPPET_PREW_MAX_LEN = 60;
MediaPlayer mPlayer;
//Bundle类型的数据与Map类型的数据相似都是以key-value的形式存储数据的
//onsaveInstanceState方法是用来保存Activity的状态的,能从onCreate的参数savedInsanceState中获得状态数据
/**
* @classname: AlarmAlertActivity
* @methodname onCreate
* @description:
* @date: 2023/12/28 11:27
* @author: wangrunze
* @param: Bundle savedInstanceState
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
requestWindowFeature(Window.FEATURE_NO_TITLE);//界面显示——无标题
final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
if (!isScreenOn()) {
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON//保持窗体点亮
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON//将窗体点亮
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON//允许窗体点亮时锁屏
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);//在手机锁屏后如果到了闹钟提示时间,点亮屏幕
}
Intent intent = getIntent();
try {
mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1));
mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId);
mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId);//根据ID从数据库中获取标签的内容
mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN ? mSnippet.substring(0,
SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info)
SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info)//判断标签片段是否达到符合长度
: mSnippet;
} catch (IllegalArgumentException e) {
e.printStackTrace();
@ -76,23 +91,39 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
mPlayer = new MediaPlayer();
if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) {
showActionDialog();
playAlarmSound();
showActionDialog();//弹出对话框
playAlarmSound();//闹钟提示音激发
} else {
finish();
}
}
/**
* @classname: AlarmAlertActivity
* @methodname isScreenOn
* @description:
* @date: 2023/12/28 11:28
* @author: wangrunze
* @return: pm.isScreenOn()
*/
private boolean isScreenOn() {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
return pm.isScreenOn();
}
/**
* @classname: AlarmAlertActivity
* @methodname playAlarmSound
* @description:
* @date: 2023/12/28 11:29
* @author: wangrunze
*/
private void playAlarmSound() {
Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM);
int silentModeStreams = Settings.System.getInt(getContentResolver(),
Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);
Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); //调用系统的铃声管理URI得到闹钟提示音
if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) {
mPlayer.setAudioStreamType(silentModeStreams);
@ -100,13 +131,13 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
}
try {
mPlayer.setDataSource(this, url);
mPlayer.prepare();
mPlayer.setLooping(true);
mPlayer.start();
mPlayer.setDataSource(this, url);//无返回值,设置多媒体数据来源
mPlayer.prepare();//准备同步
mPlayer.setLooping(true);//设置是否循环播放
mPlayer.start();//开始播放
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
e.printStackTrace();//抛出异常, 还将显示出更深的调用信息
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@ -119,22 +150,31 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
}
}
/**
* @classname: AlarmAlertActivity
* @methodname showActionDialog
* @description:
* @date: 2023/12/28 11:30
* @author: wangrunze
*/
private void showActionDialog() {
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle(R.string.app_name);
dialog.setMessage(mSnippet);
dialog.setPositiveButton(R.string.notealert_ok, this);
AlertDialog.Builder dialog = new AlertDialog.Builder(this);//用到AlertDialog.Builder中的create()新建了一个AlertDialog
dialog.setTitle(R.string.app_name);//为对话框设置标题
dialog.setMessage(mSnippet);//为对话框设置内容
dialog.setPositiveButton(R.string.notealert_ok, this);//给对话框添加"Yes"按钮
if (isScreenOn()) {
dialog.setNegativeButton(R.string.notealert_enter, this);
dialog.setNegativeButton(R.string.notealert_enter, this);//给对话框添加"no"按钮
}
dialog.show().setOnDismissListener(this);
}
//DialogInterface dialog为对话框which为选择按钮,功能为选择各种操作
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_NEGATIVE:
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_VIEW);
case DialogInterface.BUTTON_NEGATIVE://这是取消操作
Intent intent = new Intent(this, NoteEditActivity.class);//实现两个类间的数据传输
intent.setAction(Intent.ACTION_VIEW);//设置动作属性
intent.putExtra(Intent.EXTRA_UID, mNoteId);
startActivity(intent);
break;
@ -143,11 +183,25 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
}
}
/**
* @classname: AlarmAlertActivity
* @methodname onDismiss
* @description:
* @date: 2023/12/28 11:30
* @author: wangrunze
* @param:DialogInterface dialog
*/
public void onDismiss(DialogInterface dialog) {
stopAlarmSound();
finish();
}
/**
* @classname: AlarmAlertActivity
* @methodname: stopAlarmSound
* @description:
* @date: 2023/12/28 11:31
* @author: wangrunze
*/
private void stopAlarmSound() {
if (mPlayer != null) {
mPlayer.stop();
@ -156,3 +210,4 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
}
}
}

@ -71,9 +71,16 @@ 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;
@ -83,7 +90,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
public ImageView ibSetBgColor;
}
//颜色可选项的视图——色板的显示
private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>();
static {
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
@ -101,7 +108,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<Integer, Integer> sFontSizeBtnsMap = new HashMap<Integer, Integer>();
static {
sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE);
@ -118,37 +125,48 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SUPER, R.id.iv_super_select);
}
private static final String TAG = "NoteEditActivity";
private static final String TAG = "NoteEditActivity"; // 用于日志打印的标签,分类接收消息
private HeadViewHolder mNoteHeaderHolder; // 列表头视图容器持有者
private View mHeadViewPanel; // 头部视图面板
private HeadViewHolder mNoteHeaderHolder;
private View mNoteBgColorSelector; // 笔记背景颜色选择器视图
private View mHeadViewPanel;
private View mFontSizeSelector; // 字体大小选择器视图
private View mNoteBgColorSelector;
private EditText mNoteEditor; // 笔记编辑器输入框
private View mFontSizeSelector;
private View mNoteEditorPanel; // 笔记编辑器面板
private EditText mNoteEditor;
private WorkingNote mWorkingNote; // 当前正在编辑的工作笔记对象
private View mNoteEditorPanel;
private SharedPreferences mSharedPrefs; // 用于存储和检索应用偏好设置的对象
private WorkingNote mWorkingNote;
private int mFontSizeId; // 当前选中的字体大小的资源ID
private SharedPreferences mSharedPrefs;
private int mFontSizeId;
private static final String PREFERENCE_FONT_SIZE = "pref_font_size"; // 偏好设置中用于保存字体大小的键
private static final String PREFERENCE_FONT_SIZE = "pref_font_size";
private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10; // 快捷方式图标标题的最大长度
private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10;
public static final String TAG_CHECKED = String.valueOf('\u221A'); // 特殊符号,对钩(可能用于任务视图中表示任务已完成)
public static final String TAG_CHECKED = String.valueOf('\u221A');
public static final String TAG_UNCHECKED = String.valueOf('\u25A1');
public static final String TAG_UNCHECKED = String.valueOf('\u25A1'); // 特殊符号,空心方块(可能用于任务视图中表示任务未完成)
private LinearLayout mEditTextList;
private LinearLayout mEditTextList; // 线性布局可能用于动态添加或显示多个EditText
private String mUserQuery;
private Pattern mPattern;
private String mUserQuery; // 用户输入的查询字符串
private Pattern mPattern; // 用于匹配用户查询的正则表达式模式对象
/**
* @classname: NoteEditActivity
* @methodname onCreate
* @description:
* @date: 2023/12/25 8:34
* @author: Xia Yanbo
* @param:
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -164,58 +182,71 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* 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)) {
finish();
return;
intent.putExtra(Intent.EXTRA_UID, savedInstanceState.getLong(Intent.EXTRA_UID));//之前保存的意图附加其上
if (!initActivityState(intent)) { // 调用 initActivityState 方法来处理这个 Intent可能进行一些初始化工作或状态设置。
finish(); // 如果 initActivityState 方法返回 false表示初始化失败此时结束当前活动。
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);
@ -227,7 +258,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");
}
@ -247,7 +278,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
} else {
mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId, widgetType,
bgResId);
bgResId);//电话号码和提醒日期都为空,直接创建新表
}
getWindow().setSoftInputMode(
@ -263,26 +294,33 @@ 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
@ -294,11 +332,17 @@ public class NoteEditActivity extends Activity implements OnClickListener,
*/
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(
@ -311,12 +355,19 @@ 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) {
@ -332,7 +383,15 @@ 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
@ -348,13 +407,22 @@ 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:booleantruefalse
*/
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())) {
@ -362,7 +430,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
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();
@ -390,13 +464,14 @@ 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}
* idBG_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();
@ -405,53 +480,66 @@ 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()
mWorkingNote.getWidgetId()//给意图intent添加要更新的控件的id
});
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));
mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));// 设置工作笔记的背景色ID为选择的背景色ID
mNoteBgColorSelector.setVisibility(View.GONE);
} 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) {
} 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) { // 如果笔记处于检查列表模式,则获取文本并切换到列表模式(两种模式是分开的)
getWorkingText();
switchToListMode(mWorkingNote.getContent());
} else {
} else { // 否则,设置文本的外观为新的字体大小
mNoteEditor.setTextAppearance(this,
TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
}
mFontSizeSelector.setVisibility(View.GONE);
}
}
//用户按下返回键时,清楚可见的设置状态并保存便签
@Override
public void onBackPressed() {
if(clearSettingState()) {
@ -461,7 +549,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
saveNote();
super.onBackPressed();
}
//将还未被隐藏的选择器组件隐藏起来
private boolean clearSettingState() {
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE) {
mNoteBgColorSelector.setVisibility(View.GONE);
@ -472,31 +560,45 @@ 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:truefalse
*/
@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 {
@ -504,23 +606,32 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
return true;
}
/**
* @classname: NoteEditActivity
* @methodname onOptionsItemSelected
* @description:
* @date: 2023/12/25 16:22
* @author: Xia Yanbo
* @param:item 便
* @return:boolean truefalse
*/
@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);
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); // 创建一个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() {//点击事件监听器
public void onClick(DialogInterface dialog, int which) {
deleteCurrentNote();
finish();
@ -529,41 +640,47 @@ 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_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();
@ -572,69 +689,87 @@ 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.setType("text/plain");
context.startActivity(intent);
Intent intent = new Intent(Intent.ACTION_SEND);//意图为发送
intent.putExtra(Intent.EXTRA_TEXT, info);//附加要发送的信息到intent
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());
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);//设置活动为编辑
intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mWorkingNote.getFolderId());//附加包和便签的id
startActivity(intent);
}
/**
* @classname: NoteEditActivity
* @methodname deleteCurrentNote
* @description:便
* @date: 2023/12/25 21:28
* @author: Xia Yanbo
*/
private void deleteCurrentNote() {
if (mWorkingNote.existInDatabase()) {
HashSet<Long> ids = new HashSet<Long>();
if (mWorkingNote.existInDatabase()) {//检查笔记是否在数据库里
HashSet<Long> ids = new HashSet<Long>();// 创建一个空的HashSet用于存储笔记ID
long id = mWorkingNote.getNoteId();
if (id != Notes.ID_ROOT_FOLDER) {
if (id != Notes.ID_ROOT_FOLDER) {// 如果笔记ID不是根文件夹ID则将其添加到HashSet中
ids.add(id);
} else {
} else {// 如果笔记ID是根文件夹ID则打印错误日志因为这不该发生
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
* @param:
* @param:
* @param:
* @return:
*/
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 {
@ -644,26 +779,34 @@ 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);
showToast(R.string.error_note_empty_for_clock);//显示toast消息用于提醒用户输入
}
}
//更新当前的控件
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(
@ -677,43 +820,44 @@ 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));
mEditTextList.addView(getListItem(item, index));//添加列表项标记实现的关键步骤addView
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)) {
@ -721,7 +865,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);
@ -730,14 +874,33 @@ 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);
edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
// 设置文本的外观样式使用传入的字体大小ID作为参数。
edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));//标记,能改动文字大小的关键所在
// 获取CheckBox组件
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 {
@ -746,6 +909,7 @@ 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);
@ -756,24 +920,29 @@ 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());
@ -787,7 +956,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteEditor.setVisibility(View.VISIBLE);
}
}
/**
* @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) {
@ -806,11 +982,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();
@ -826,7 +1002,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
return saved;
}
//保存便签并发送到桌面
private void sendToDesktop() {
/**
* Before send message to home, we should make sure that current
@ -861,14 +1037,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);
}

@ -36,16 +36,23 @@ 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<String, Integer> sSchemaActionResMap = new HashMap<String, Integer>();
static {
sSchemaActionResMap.put(SCHEME_TEL, R.string.note_link_tel);
@ -55,53 +62,65 @@ 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();
@ -112,15 +131,24 @@ 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) {
@ -137,7 +165,16 @@ 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) {
@ -166,11 +203,20 @@ 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);
@ -178,19 +224,27 @@ 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) {
int selStart = getSelectionStart();
int selEnd = getSelectionEnd();
if (getText() instanceof Spanned) {//检查文本的类型 Spanned是一个接口
int selStart = getSelectionStart();//所选择文本的开始位置
int selEnd = getSelectionEnd();//所选择文本的结束位置
//确定选择开始的较小值和较大值,方便直接做差
int min = Math.min(selStart, selEnd);
int max = Math.max(selStart, selEnd);
final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class);
//获取选择的文本范围内获取所有的 URLSpan 对象。URLSpan 是用于表示文本中的链接的。
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);
@ -201,9 +255,10 @@ 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);
@ -212,6 +267,6 @@ public class NoteEditText extends EditText {
});
}
}
super.onCreateContextMenu(menu);
super.onCreateContextMenu(menu);//调用父类方法
}
}

Loading…
Cancel
Save