feifei 2 years ago
parent eeb153da92
commit cb795b9b60

3
.idea/.gitignore vendored

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/report.iml" filepath="$PROJECT_DIR$/.idea/report.iml" />
</modules>
</component>
</project>

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -201,15 +201,25 @@ public class NoteEditActivity extends Activity implements OnClickListener,
@Override
/**
* Activity
* @param savedInstanceState
*/
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// 检查之前是否保存了状态数据并且包含Intent.EXTRA_UID键
if (savedInstanceState != null && savedInstanceState.containsKey(Intent.EXTRA_UID)) {
// 创建一个查看指定UID的意图
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra(Intent.EXTRA_UID, savedInstanceState.getLong(Intent.EXTRA_UID));
// 初始化活动状态并判断是否成功
if (!initActivityState(intent)) {
// 如果初始化活动状态失败,则结束当前活动
finish();
return;
}
// 打印日志,提示从被终止的活动中恢复
Log.d(TAG, "Restoring from killed activity");
}
}
@ -220,37 +230,51 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* then jump to the NotesListActivity
*/
mWorkingNote = null;
// 检查Intent的Action是否是ACTION_VIEW
if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) {
long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0);
mUserQuery = "";
/**
* Starting from the searched result
*
*/
if (intent.hasExtra(SearchManager.EXTRA_DATA_KEY)) {
// 如果Intent带有EXTRA_DATA_KEY则更新noteId和mUserQuery
noteId = Long.parseLong(intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY);
}
// 检查数据库中是否存在指定类型为TYPE_NOTE的noteId
if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) {
// 如果不存在则跳转到NotesListActivity并显示错误信息最后结束当前Activity
Intent jump = new Intent(this, NotesListActivity.class);
startActivity(jump);
showToast(R.string.error_note_not_exist);
finish();
return false;
return false; // 建议在此处加入日志信息以记录错误
} else {
// 如果存在加载对应noteId的WorkingNote对象
mWorkingNote = WorkingNote.load(this, noteId);
if (mWorkingNote == null) {
// 如果加载失败记录错误日志并结束当前Activity
Log.e(TAG, "load note failed with note id" + noteId);
finish();
return false;
}
}
// 调用Activity的getWindow()方法来获取当前窗口
getWindow().setSoftInputMode(
// 设置软键盘的显示状态和窗口调整选项为组合模式
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
// 使用SOFT_INPUT_STATE_HIDDEN标志
// 当用户进入该Activity时软键盘默认情况下是隐藏的。
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
// 使用SOFT_INPUT_ADJUST_RESIZE标志
// 当软键盘显示时允许当前Activity的窗口被调整大小
// 以留出软键盘所需的空间,这样内容就不会被软键盘覆盖。
} else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) {
// New note
// 如果Intent的Action是ACTION_INSERT_OR_EDIT
// 创建新的笔记
long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0);
int widgetId = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
@ -259,7 +283,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
int bgResId = intent.getIntExtra(Notes.INTENT_EXTRA_BACKGROUND_ID,
ResourceParser.getDefaultBgId(this));
// Parse call-record note
// 获取Intent中的电话号码和通话日期
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
long callDate = intent.getLongExtra(Notes.INTENT_EXTRA_CALL_DATE, 0);
if (callDate != 0 && phoneNumber != null) {
@ -267,32 +291,40 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Log.w(TAG, "The call record number is null");
}
long noteId = 0;
// 通过电话号码和通话日期从数据库中获取对应的noteId
if ((noteId = DataUtils.getNoteIdByPhoneNumberAndCallDate(getContentResolver(),
phoneNumber, callDate)) > 0) {
// 如果存在对应的noteId则加载该笔记
mWorkingNote = WorkingNote.load(this, noteId);
if (mWorkingNote == null) {
// 加载失败的话记录错误日志并结束当前Activity
Log.e(TAG, "load call note failed with note id" + noteId);
finish();
return false;
}
} else {
// 如果不存在对应的noteId则创建一个新的通话笔记
mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId,
widgetType, bgResId);
mWorkingNote.convertToCallNote(phoneNumber, callDate);
}
} else {
// 如果没有有效的电话号码和通话日期,则创建一个新的空白笔记
mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId, widgetType,
bgResId);
}
// 设置输入法模式为:自动调整大小,并且显示输入法
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
// 对Intent没有指定的Action进行错误处理
} else {
Log.e(TAG, "Intent not specified action, should not support");
finish();
return false;
}
// 设置监听器来监听设置状态的改变
mWorkingNote.setOnSettingStatusChangedListener(this);
return true;
}
@ -303,104 +335,125 @@ public class NoteEditActivity extends Activity implements OnClickListener,
initNoteScreen();//初始化便签屏幕
}
/**
*
*/
private void initNoteScreen() {
// 设置笔记编辑器文本外观
mNoteEditor.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
// 根据WorkingNote的CheckListMode设置编辑器模式
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
switchToListMode(mWorkingNote.getContent());
} else {
// 设置笔记编辑器内容为通过搜索结果高亮后的内容,并将光标移到末尾
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
mNoteEditor.setSelection(mNoteEditor.getText().length());
}
// 隐藏背景选择器中的所有选项
for (Integer id : sBgSelectorSelectionMap.keySet()) {
findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE);
}
// 设置头部视图和笔记编辑器的背景
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
// 设置最后修改时间
mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(this,
mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
| DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
| DateUtils.FORMAT_SHOW_YEAR));
// 显示警告标头
showAlertHeader();
//灏嗘湁鍥剧墖璺<E5A296>緞鐨勪綅缃<E7B685>浆鎹<E6B586>负鍥剧墖
// 将文本中的图片路径转换为实际图片
convertToImage();
}
//路径字符串格式 转换为 图片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
NoteEditText noteEditText = (NoteEditText) findViewById(R.id.note_edit_view); // 获取编辑器视图
Editable editable = noteEditText.getText(); // 1. 获取文本
String noteText = editable.toString(); // 2. 将笔记内容转换为字符串
int length = editable.length(); // 获取长度
// 3. 寻找图片片段 [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);//获取到了图片路径
String imgFragment = noteText.substring(i, j+1); // imgFragment 为图片路径片段
if(imgFragment.length() > 15 && imgFragment.endsWith("[/local]") && imgFragment.startsWith("[local]")){
int limit = 7; // [local]为7个字符
// [/local]再加15个字符剩下的为实际图片路径
int len = imgFragment.length()-15;
// 在[local]之后的len个字符为图片路径
String path = imgFragment.substring(limit,limit+len);// 获取实际图片路径
Bitmap bitmap = null;
Log.d(TAG, "图片路径"+path);
Log.d(TAG, "图片路径:"+path);
try {
bitmap = BitmapFactory.decodeFile(path);//将图片路径解码为图片格式
bitmap = BitmapFactory.decodeFile(path);// 将图片路径转换为bitmap格式
} catch (Exception e) {
e.printStackTrace();
}
if(bitmap!=null){ //若图片存在
Log.d(TAG, "图片不为null");
if(bitmap!=null){ // 如果图片不为null
Log.d(TAG, "图片不为null");
ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap);
//4.创建一个SpannableString对象以便插入用ImageSpan对象封装的图像
// 4. 创建一个SpannableString并将其包装为ImageSpan
String ss = "[local]" + path + "[/local]";
SpannableString spannableString = new SpannableString(ss);
//5.将指定的标记对象附加到文本的开始...结束范围
// 5. 设置span的范围并将其中的部分替换为图像
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.在路径的起始位置插入图片
edit_text.delete(i, i+len+15); // 6. 删除图片路径部分
edit_text.insert(i, spannableString); // 7. 插入图片到指定位置
}
}
}
}
}
//重写onActivityResult()来处理返回的数据
/**
* ActivityResult
*/
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.获得图片的真实路径
Uri originalUri = intent.getData(); // 1. 获取图片的真实路径
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(resolver.openInputStream(originalUri));//2.解码图片
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对象
// 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中光标所在位置
// 4. 使用[local][/local]标签包裹路径并插入到note中的指定位置
String imgFragment= "[local]" + path + "[/local]";
// 创建一个SpannableString并将其包装为ImageSpan
SpannableString spannableString = new SpannableString(imgFragment);
spannableString.setSpan(imageSpan, 0, imgFragment.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);
int index = e.getSelectionStart(); // 获取光标的位置
Log.d(TAG, "Index: " + index);
Editable edit_text = e.getEditableText();
edit_text.insert(index, spannableString); //将图片插入到光标所在位置
edit_text.insert(index, spannableString); // 将图片插入到光标位置
mWorkingNote.mContent = e.getText().toString();
//6.把改动提交到数据库中,两个数据库表都要改的
// 6. 将更新后的内容提交到数据库
ContentResolver contentResolver = getContentResolver();
ContentValues contentValues = new ContentValues();
final long id = mWorkingNote.getNoteId();
@ -410,15 +463,15 @@ public class NoteEditActivity extends Activity implements OnClickListener,
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();
} else {
Toast.makeText(NoteEditActivity.this, "获取图片失败", Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
//获取文件的real path
//<EFBFBD><EFBFBD>ȡ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>real path
public String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
@ -644,15 +697,18 @@ public class NoteEditActivity extends Activity implements OnClickListener,
public void onClick(View v) {
int id = v.getId();
if (id == R.id.btn_set_bg_color) {
// 显示笔记背景颜色选择器,并显示当前选中的颜色
mNoteBgColorSelector.setVisibility(View.VISIBLE);
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.VISIBLE);
} else if (sBgSelectorBtnsMap.containsKey(id)) {
// 隐藏当前选中的颜色,设置新的背景颜色并隐藏选择器
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.GONE);
mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));
mNoteBgColorSelector.setVisibility(View.GONE);
} else if (sFontSizeBtnsMap.containsKey(id)) {
// 切换字体大小更新SharedPreferences中的设置显示当前选中的字体大小
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.GONE);
mFontSizeId = sFontSizeBtnsMap.get(id);
mSharedPrefs.edit().putInt(PREFERENCE_FONT_SIZE, mFontSizeId).commit();
@ -697,40 +753,66 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
@Override
/**
* 便
* @param menu
* @return truefalse
*/
public boolean onPrepareOptionsMenu(Menu menu) {
// 如果Activity即将被销毁则不显示选项菜单
if (isFinishing()) {
return true;
}
// 清除设置状态
clearSettingState();
menu.clear();
// 根据便签所属文件夹的不同加载不同的菜单项
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;
}
@Override
/**
*
* @param item
* @return true
*/
public boolean onOptionsItemSelected(MenuItem item) {
// 获取被点击菜单项的id
int itemId = item.getItemId();
// 如果点击的是新建笔记菜单项
if (itemId == R.id.menu_new_note) {
createNewNote();
} else if (itemId == R.id.menu_delete) {
createNewNote(); // 调用创建新笔记的方法
}
// 如果点击的是删除菜单项
else if (itemId == 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() {
public void onClick(DialogInterface dialog, int which) {
@ -738,25 +820,38 @@ public class NoteEditActivity extends Activity implements OnClickListener,
finish();
}
});
builder.setNegativeButton(android.R.string.cancel, null);
builder.show();
} else if (itemId == R.id.menu_font_size) {
mFontSizeSelector.setVisibility(View.VISIBLE);
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);
} else if (itemId == R.id.menu_list_mode) {
builder.setNegativeButton(android.R.string.cancel, null); // 取消按钮无操作
builder.show(); // 显示对话框
}
// 如果点击的是字体大小菜单项
else if (itemId == R.id.menu_font_size) {
mFontSizeSelector.setVisibility(View.VISIBLE); // 显示字体大小选择器
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE); // 根据字体大小id显示相应的视图
}
// 如果点击的是列表模式菜单项
else if (itemId == R.id.menu_list_mode) {
// 切换笔记的列表模式
mWorkingNote.setCheckListMode(mWorkingNote.getCheckListMode() == 0 ?
TextNote.MODE_CHECK_LIST : 0);
} else if (itemId == R.id.menu_share) {
getWorkingText();
sendTo(this, mWorkingNote.getContent());
} else if (itemId == R.id.menu_send_to_desktop) {
sendToDesktop();
} else if (itemId == R.id.menu_alert) {
setReminder();
} else if (itemId == R.id.menu_delete_remind) {
mWorkingNote.setAlertDate(0, false);
}
return true;
// 如果点击的是分享菜单项
else if (itemId == R.id.menu_share) {
getWorkingText(); // 获取工作中的文本
sendTo(this, mWorkingNote.getContent()); // 发送文本内容
}
// 如果点击的是发送到桌面菜单项
else if (itemId == R.id.menu_send_to_desktop) {
sendToDesktop(); // 发送到桌面
}
// 如果点击的是提醒菜单项
else if (itemId == R.id.menu_alert) {
setReminder(); // 设置提醒
}
// 如果点击的是删除提醒菜单项
else if (itemId == R.id.menu_delete_remind) {
mWorkingNote.setAlertDate(0, false); // 将笔记的提醒日期设为0并取消提醒
}
return true; // 事件已处理返回true
}
private void setReminder() {
@ -788,26 +883,31 @@ public class NoteEditActivity extends Activity implements OnClickListener,
startActivity(intent);
}
/**
*
*
*
*/
private void deleteCurrentNote() {
if (mWorkingNote.existInDatabase()) {
HashSet<Long> ids = new HashSet<Long>();
long id = mWorkingNote.getNoteId();
if (id != Notes.ID_ROOT_FOLDER) {
ids.add(id);
if (mWorkingNote.existInDatabase()) { // 检查当前笔记是否存在于数据库中
HashSet<Long> ids = new HashSet<Long>(); // 创建一个存储笔记ID的集合
long id = mWorkingNote.getNoteId(); // 获取当前笔记的ID
if (id != Notes.ID_ROOT_FOLDER) { // 如果当前笔记不是根文件夹中的笔记
ids.add(id); // 将笔记ID添加到集合中
} else {
Log.d(TAG, "Wrong note id, should not happen");
Log.d(TAG, "Wrong note id, should not happen"); // 记录错误日志表示不应该出现的笔记ID异常情况
}
if (!isSyncMode()) {
if (!DataUtils.batchDeleteNotes(getContentResolver(), ids)) {
Log.e(TAG, "Delete Note error");
if (!isSyncMode()) { // 如果不是同步模式
if (!DataUtils.batchDeleteNotes(getContentResolver(), ids)) { // 执行批量删除操作
Log.e(TAG, "Delete Note error"); // 记录错误日志,表示删除笔记出错
}
} else {
if (!DataUtils.batchMoveToFolder(getContentResolver(), ids, Notes.ID_TRASH_FOLER)) {
Log.e(TAG, "Move notes to trash folder error, should not happens");
} 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() {

Loading…
Cancel
Save