You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
xiaomi_mini/src/main/java/net/micode/notes/ui/NoteEditActivity.java

1270 lines
57 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.ui;
import android.app.Activity;
import android.app.AlarmManager;
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.support.v7.app.AppCompatActivity;
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;
import android.view.MenuItem;
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;
import android.widget.Toast;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.TextNote;
import net.micode.notes.model.WorkingNote;
import net.micode.notes.model.WorkingNote.NoteSettingChangedListener;
import net.micode.notes.tool.DataUtils;
import net.micode.notes.tool.ResourceParser;
import net.micode.notes.tool.ResourceParser.TextAppearanceResources;
import net.micode.notes.ui.DateTimePickerDialog.OnDateTimeSetListener;
import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
import net.micode.notes.widget.NoteWidgetProvider_2x;
import net.micode.notes.widget.NoteWidgetProvider_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 AppCompatActivity implements OnClickListener,
NoteSettingChangedListener, OnTextViewChangeListener {
//定义视图组件的基本数据(后面出现在了操作菜可选项里)
private class HeadViewHolder {
public TextView tvModified;
public ImageView ivAlertIcon;
public TextView tvAlertDate;
public ImageView ibSetBgColor;
}
//颜色可选项的视图——色板的显示
private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>();
static {
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
sBgSelectorBtnsMap.put(R.id.iv_bg_red, ResourceParser.RED);
sBgSelectorBtnsMap.put(R.id.iv_bg_blue, ResourceParser.BLUE);
sBgSelectorBtnsMap.put(R.id.iv_bg_green, ResourceParser.GREEN);
sBgSelectorBtnsMap.put(R.id.iv_bg_white, ResourceParser.WHITE);
}
private static final Map<Integer, Integer> sBgSelectorSelectionMap = new HashMap<Integer, Integer>();
static {
sBgSelectorSelectionMap.put(ResourceParser.YELLOW, R.id.iv_bg_yellow_select);
sBgSelectorSelectionMap.put(ResourceParser.RED, R.id.iv_bg_red_select);
sBgSelectorSelectionMap.put(ResourceParser.BLUE, R.id.iv_bg_blue_select);
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);
sFontSizeBtnsMap.put(R.id.ll_font_small, ResourceParser.TEXT_SMALL);
sFontSizeBtnsMap.put(R.id.ll_font_normal, ResourceParser.TEXT_MEDIUM);
sFontSizeBtnsMap.put(R.id.ll_font_super, ResourceParser.TEXT_SUPER);
}
private static final Map<Integer, Integer> sFontSelectorSelectionMap = new HashMap<Integer, Integer>();
static {
sFontSelectorSelectionMap.put(ResourceParser.TEXT_LARGE, R.id.iv_large_select);
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SMALL, R.id.iv_small_select);
sFontSelectorSelectionMap.put(ResourceParser.TEXT_MEDIUM, R.id.iv_medium_select);
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SUPER, R.id.iv_super_select);
}
private static final String TAG = "NoteEditActivity"; // 用于日志打印的标签,分类接收消息
private HeadViewHolder mNoteHeaderHolder; // 列表头视图容器持有者
private View mHeadViewPanel; // 头部视图面板
private View mNoteBgColorSelector; // 笔记背景颜色选择器视图
private View mFontSizeSelector; // 字体大小选择器视图
private EditText mNoteEditor; // 笔记编辑器输入框
private View mNoteEditorPanel; // 笔记编辑器面板
private WorkingNote mWorkingNote; // 当前正在编辑的工作笔记对象
private SharedPreferences mSharedPrefs; // 用于存储和检索应用偏好设置的对象
private int mFontSizeId; // 当前选中的字体大小的资源ID
private static final String PREFERENCE_FONT_SIZE = "pref_font_size"; // 偏好设置中用于保存字体大小的键
private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10; // 快捷方式图标标题的最大长度
public static final String TAG_CHECKED = String.valueOf('\u221A'); // 特殊符号,对钩(可能用于任务视图中表示任务已完成)
public static final String TAG_UNCHECKED = String.valueOf('\u25A1'); // 特殊符号,空心方块(可能用于任务视图中表示任务未完成)
private LinearLayout mEditTextList; // 线性布局可能用于动态添加或显示多个EditText
private String mUserQuery; // 用户输入的查询字符串
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);
this.setContentView(R.layout.note_edit);
if (savedInstanceState == null && !initActivityState(getIntent())) {
finish();
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)) {//检查保存的状态是否为空,是否包含特定意图
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; // 结束当前方法。
}
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())) {//检查意图是否是查看
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);//跳转到笔记集活动中
showToast(R.string.error_note_not_exist);
finish();
return false;
} else {
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())) {//否则,意图并非查看的情况
// 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);
int widgetType = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_TYPE,
Notes.TYPE_WIDGET_INVALIDE);
int bgResId = intent.getIntExtra(Notes.INTENT_EXTRA_BACKGROUND_ID,
ResourceParser.getDefaultBgId(this));
// Parse call-record note
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
long callDate = intent.getLongExtra(Notes.INTENT_EXTRA_CALL_DATE, 0);
if (callDate != 0 && phoneNumber != null) {//负责消息通知
if (TextUtils.isEmpty(phoneNumber)) {
Log.w(TAG, "The call record number is null");
}
long noteId = 0;
if ((noteId = DataUtils.getNoteIdByPhoneNumberAndCallDate(getContentResolver(),
phoneNumber, callDate)) > 0) {
mWorkingNote = WorkingNote.load(this, noteId);
if (mWorkingNote == null) {
Log.e(TAG, "load call note failed with note id" + noteId);
finish();
return false;
}
} else {
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);
} else {
Log.e(TAG, "Intent not specified action, should not support");
finish();
return false;
}
mWorkingNote.setOnSettingStatusChangedListener(this);
return true;
}
@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
| DateUtils.FORMAT_SHOW_YEAR));
/**
* 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()) {//判断时间是否到达
mNoteHeaderHolder.tvAlertDate.setText(R.string.note_alert_expired);
} else {
mNoteHeaderHolder.tvAlertDate.setText(DateUtils.getRelativeTimeSpanString(
mWorkingNote.getAlertDate(), time, DateUtils.MINUTE_IN_MILLIS));
}
mNoteHeaderHolder.tvAlertDate.setVisibility(View.VISIBLE);
mNoteHeaderHolder.ivAlertIcon.setVisibility(View.VISIBLE);
} else {
mNoteHeaderHolder.tvAlertDate.setVisibility(View.GONE);
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) {
super.onSaveInstanceState(outState);
/**
* For new note without note id, we should firstly save it to
* generate a id. If the editing note is not worth saving, there
* is no id which is equivalent to create new note
*/
if (!mWorkingNote.existInDatabase()) {
saveNote();
}
outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId());
Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState");
}
/**
* @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
&& !inRangeOfView(mNoteBgColorSelector, ev)) {
mNoteBgColorSelector.setVisibility(View.GONE);
return true;
}
if (mFontSizeSelector.getVisibility() == View.VISIBLE
&& !inRangeOfView(mFontSizeSelector, ev)) {
mFontSizeSelector.setVisibility(View.GONE);
return true;
}
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);//获取视图在屏幕上的位置
int x = location[0];
int y = location[1];
if (ev.getX() < x//判断事件有没有在视图所在的范围之内
|| ev.getX() > (x + view.getWidth())
|| ev.getY() < y
|| ev.getY() > (y + view.getHeight())) {
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();
mNoteHeaderHolder.tvModified = (TextView) findViewById(R.id.tv_modified_date);
mNoteHeaderHolder.ivAlertIcon = (ImageView) findViewById(R.id.iv_alert_icon);
mNoteHeaderHolder.tvAlertDate = (TextView) findViewById(R.id.tv_alert_date);
mNoteHeaderHolder.ibSetBgColor = (ImageView) findViewById(R.id.btn_set_bg_color);
mNoteHeaderHolder.ibSetBgColor.setOnClickListener(this);
mNoteEditor = (EditText) findViewById(R.id.note_edit_view);
mNoteEditorPanel = findViewById(R.id.sv_note_edit);
mNoteBgColorSelector = findViewById(R.id.note_bg_color_selector);
for (int id : sBgSelectorBtnsMap.keySet()) {
ImageView iv = (ImageView) findViewById(id);
iv.setOnClickListener(this);
}
mFontSizeSelector = findViewById(R.id.font_size_selector);
for (int id : sFontSizeBtnsMap.keySet()) {
View view = findViewById(id);
view.setOnClickListener(this);
};
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
mFontSizeId = mSharedPrefs.getInt(PREFERENCE_FONT_SIZE, ResourceParser.BG_DEFAULT_FONT_SIZE);
/**
* 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();
if(saveNote()) {
Log.d(TAG, "Note data was saved with length:" + mWorkingNote.getContent().length());
}
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) {//检查当前工作笔记的控件类型,给对应的提供类
intent.setClass(this, NoteWidgetProvider_2x.class);
} else if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_4X) {
intent.setClass(this, NoteWidgetProvider_4x.class);
} else {//控件类型不受支持,打印错误日志
Log.e(TAG, "Unspported widget type");
return;
}
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
mWorkingNote.getWidgetId()//给意图intent添加要更新的控件的id
});
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) {// 如果点击的是设置背景色的按钮
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));// 设置工作笔记的背景色ID为选择的背景色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) { // 如果笔记处于检查列表模式,则获取文本并切换到列表模式(两种模式是分开的)
getWorkingText();
switchToListMode(mWorkingNote.getContent());
} else { // 否则,设置文本的外观为新的字体大小
mNoteEditor.setTextAppearance(this,
TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
}
mFontSizeSelector.setVisibility(View.GONE);
}
}
//用户按下返回键时,清楚可见的设置状态并保存便签
@Override
public void onBackPressed() {
if(clearSettingState()) {
return;
}
saveNote();
super.onBackPressed();
}
//将还未被隐藏的选择器组件隐藏起来
private boolean clearSettingState() {
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE) {
mNoteBgColorSelector.setVisibility(View.GONE);
return true;
} else if (mFontSizeSelector.getVisibility() == View.VISIBLE) {
mFontSizeSelector.setVisibility(View.GONE);
return true;
}
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() {//点击事件监听器
public void onClick(DialogInterface dialog, int which) {
deleteCurrentNote();
finish();
}
});
builder.setNegativeButton(android.R.string.cancel, null);
builder.show();
}
//字体大小功能项
else if(item.getItemId()== R.id.menu_font_size)
{
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());//分享出去
}
//发送到桌面
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() {//监听设置的时间
public void OnDateTimeSet(AlertDialog dialog, long date) {
mWorkingNote.setAlertDate(date , true);//设置提醒的日期时间
}
});
d.show();
}
/**
* 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);//根据意图开始发送信息
}
//创建一个新的便签
private void createNewNote() {
// Firstly, save current editing notes
saveNote();//保存当前便签
// For safety, start a new NoteEditActivity
finish();//销毁资源,关闭当前便签
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);//设置活动为编辑
intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mWorkingNote.getFolderId());//附加包和便签的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>();// 创建一个空的HashSet用于存储笔记ID
long id = mWorkingNote.getNoteId();
if (id != Notes.ID_ROOT_FOLDER) {// 如果笔记ID不是根文件夹ID则将其添加到HashSet中
ids.add(id);
} else {// 如果笔记ID是根文件夹ID则打印错误日志因为这不该发生
Log.d(TAG, "Wrong note id, should not happen");
}
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");
}
}
}
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();//不在数据库先保存
}
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));//获取系统的闹钟服务
showAlertHeader();
if(!set) {//取消设置闹钟
alarmManager.cancel(pendingIntent);
} else {//设置闹钟
alarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent);
}
} else {
/**
* There is the condition that user has input nothing (the note is
* not worthy saving), we have no note id, remind the user that he
* should input something
*/
Log.e(TAG, "Clock alert setting error");
showToast(R.string.error_note_empty_for_clock);//显示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();//获取子项的数量
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);//移除指定索引号的子项
NoteEditText edit = null;
if(index == 0) {
edit = (NoteEditText) mEditTextList.getChildAt(0).findViewById(
R.id.et_edit_text);
} else {
edit = (NoteEditText) mEditTextList.getChildAt(index - 1).findViewById(
R.id.et_edit_text);
}
int length = edit.length();
edit.append(text);
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");//超出编辑列表的边界
}
//根据索引和文本获取列表项视图
View view = getListItem(text, index);
mEditTextList.addView(view, index);
NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
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));//添加列表项标记实现的关键步骤addViewgetlistitem
index++;
}
}
mEditTextList.addView(getListItem("", index));
mEditTextList.getChildAt(index).findViewById(R.id.et_edit_text).requestFocus();
mNoteEditor.setVisibility(View.GONE);//用于一般模式的编辑组件隐藏
mEditTextList.setVisibility(View.VISIBLE);//用于任务清单模式的编辑组件显示
}
//高亮显示用户查询的关键字
private Spannable getHighlightQueryResult(String fullText, String userQuery) {
SpannableString spannable = new SpannableString(fullText == null ? "" : fullText);
if (!TextUtils.isEmpty(userQuery)) {
mPattern = Pattern.compile(userQuery);
Matcher m = mPattern.matcher(fullText);
int start = 0;
while (m.find(start)) {
spannable.setSpan(//使用资源中的颜色(标记:可参考用作设计颜色)
new BackgroundColorSpan(this.getResources().getColor(
R.color.user_query_highlight)), m.start(), m.end(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
start = m.end();
}
}
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组件
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 {
edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
}
}
});
// 根据item的开头判断是否为已选或未选并设置相应的CheckBox状态和文本绘制样式。
if (item.startsWith(TAG_CHECKED)) {
cb.setChecked(true);
edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
item = item.substring(TAG_CHECKED.length(), item.length()).trim();
} else if (item.startsWith(TAG_UNCHECKED)) {
cb.setChecked(false);
edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
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());
} else {
if (!getWorkingText()) {
mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ",
""));
}
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) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mEditTextList.getChildCount(); i++) {
View view = mEditTextList.getChildAt(i);
NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
if (!TextUtils.isEmpty(edit.getText())) {
if (((CheckBox) view.findViewById(R.id.cb_edit_item)).isChecked()) {
sb.append(TAG_CHECKED).append(" ").append(edit.getText()).append("\n");
hasChecked = true;
} else {
sb.append(TAG_UNCHECKED).append(" ").append(edit.getText()).append("\n");
}
}
}
mWorkingNote.setWorkingText(sb.toString());
} else {
mWorkingNote.setWorkingText(mNoteEditor.getText().toString());//不做标记值的更改
}
return hasChecked;
}
//保存便签
private boolean saveNote() {
getWorkingText();
boolean saved = mWorkingNote.saveNote();
if (saved) {
/**
* There are two modes from List view to edit view, open one note,
* create/edit a node. Opening node requires to the original
* position in the list when back from edit view, while creating a
* new node requires to the top of the list. This code
* {@link #RESULT_OK} is used to identify the create/edit state
*/
setResult(RESULT_OK);
}
return saved;
}
//保存便签并发送到桌面
private void sendToDesktop() {
/**
* Before send message to home, we should make sure that current
* editing note is exists in databases. So, for new note, firstly
* save it
*/
if (!mWorkingNote.existInDatabase()) {
saveNote();
}
if (mWorkingNote.getNoteId() > 0) {
Intent sender = new Intent();
Intent shortcutIntent = new Intent(this, NoteEditActivity.class);
shortcutIntent.setAction(Intent.ACTION_VIEW);
shortcutIntent.putExtra(Intent.EXTRA_UID, mWorkingNote.getNoteId());
sender.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
sender.putExtra(Intent.EXTRA_SHORTCUT_NAME,
makeShortcutIconTitle(mWorkingNote.getContent()));
sender.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
Intent.ShortcutIconResource.fromContext(this, R.drawable.icon_app));
sender.putExtra("duplicate", true);
sender.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
showToast(R.string.info_note_enter_desktop);
sendBroadcast(sender);
} else {
/**
* There is the condition that user has input nothing (the note is
* not worthy saving), we have no note id, remind the user that he
* should input something
*/
Log.e(TAG, "Send to desktop error");
showToast(R.string.error_note_empty_for_send_to_desktop);
}
}
//生成快捷方式图标的标题
private String makeShortcutIconTitle(String content) {
content = content.replace(TAG_CHECKED, "");
content = content.replace(TAG_UNCHECKED, "");
return content.length() > SHORTCUT_ICON_TITLE_MAX_LEN ? content.substring(0,
SHORTCUT_ICON_TITLE_MAX_LEN) : content;
}
//消息传递
private void showToast(int resId) {
showToast(resId, Toast.LENGTH_SHORT);
}
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());
}
}