|
|
@ -158,7 +158,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void onTextChange(String text) {
|
|
|
|
public void onTextChange(String text) {
|
|
|
|
mText = text;
|
|
|
|
mText = text;
|
|
|
|
mNoteLength = textChange(mText).length();
|
|
|
|
mNoteLength = removeBlank(textChange(mText)).length();
|
|
|
|
mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(NoteEditActivity.this,
|
|
|
|
mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(NoteEditActivity.this,
|
|
|
|
mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
|
|
|
|
mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
|
|
|
|
| DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
|
|
|
|
| DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
|
|
|
@ -401,7 +401,18 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
StringBuilder stringBuilder = new StringBuilder(oriText);
|
|
|
|
StringBuilder stringBuilder = new StringBuilder(oriText);
|
|
|
|
// 移除所有<>
|
|
|
|
// 移除所有<>
|
|
|
|
removeAngleBrackets(stringBuilder);
|
|
|
|
removeAngleBrackets(stringBuilder);
|
|
|
|
// 移除换行符和空格
|
|
|
|
// 将 替换为普通空格
|
|
|
|
|
|
|
|
int index = stringBuilder.indexOf(" ");
|
|
|
|
|
|
|
|
while (index != -1) {
|
|
|
|
|
|
|
|
stringBuilder.replace(index, index + 6, " ");
|
|
|
|
|
|
|
|
index = stringBuilder.indexOf(" ", index + 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return stringBuilder.toString();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String removeBlank(String oriText) {
|
|
|
|
|
|
|
|
StringBuilder stringBuilder = new StringBuilder(oriText);
|
|
|
|
|
|
|
|
// 移除换行符和其他空格
|
|
|
|
for (int i = 0; i < stringBuilder.length(); i++) {
|
|
|
|
for (int i = 0; i < stringBuilder.length(); i++) {
|
|
|
|
char c = stringBuilder.charAt(i);
|
|
|
|
char c = stringBuilder.charAt(i);
|
|
|
|
if (c == '\n' || c == ' ') {
|
|
|
|
if (c == '\n' || c == ' ') {
|
|
|
@ -709,7 +720,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void onTextChange(String text) {
|
|
|
|
public void onTextChange(String text) {
|
|
|
|
mText = text;
|
|
|
|
mText = text;
|
|
|
|
mNoteLength = textChange(mText).length();
|
|
|
|
mNoteLength = removeBlank(textChange(mText)).length();
|
|
|
|
mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(NoteEditActivity.this,
|
|
|
|
mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(NoteEditActivity.this,
|
|
|
|
mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
|
|
|
|
mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
|
|
|
|
| DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
|
|
|
|
| DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
|
|
|
@ -1182,7 +1193,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public void onCheckListModeChanged(int oldMode, int newMode) {
|
|
|
|
public void onCheckListModeChanged(int oldMode, int newMode) {
|
|
|
|
if (newMode == TextNote.MODE_CHECK_LIST) {
|
|
|
|
if (newMode == TextNote.MODE_CHECK_LIST) {
|
|
|
|
switchToListMode(mText.toString());
|
|
|
|
switchToListMode(textChange(mText));
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if (!getWorkingText()) {
|
|
|
|
if (!getWorkingText()) {
|
|
|
|
mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ",
|
|
|
|
mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ",
|
|
|
@ -1229,7 +1240,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mWorkingNote.setWorkingText(sb.toString());//利用编辑好的字符串设置运行便签的内容
|
|
|
|
mWorkingNote.setWorkingText(sb.toString());//利用编辑好的字符串设置运行便签的内容
|
|
|
|
} else {// 若不是该模式直接用编辑器中的内容设置运行中标签的内容
|
|
|
|
} else {// 若不是该模式直接用编辑器中的内容设置运行中标签的内容
|
|
|
|
mWorkingNote.setWorkingText(mText.toString());
|
|
|
|
mWorkingNote.setWorkingText(textChange(mText));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return hasChecked;
|
|
|
|
return hasChecked;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1243,6 +1254,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
private boolean saveNote() {
|
|
|
|
private boolean saveNote() {
|
|
|
|
getWorkingText();
|
|
|
|
getWorkingText();
|
|
|
|
boolean saved = mWorkingNote.saveNote();
|
|
|
|
boolean saved = mWorkingNote.saveNote();
|
|
|
|
|
|
|
|
if (TextUtils.isEmpty(mWorkingNote.getContent())) {
|
|
|
|
|
|
|
|
deleteCurrentNote();//删除当前便签
|
|
|
|
|
|
|
|
saved = false; // 标记为未保存
|
|
|
|
|
|
|
|
}
|
|
|
|
//运行 getWorkingText()之后保存
|
|
|
|
//运行 getWorkingText()之后保存
|
|
|
|
if (saved) {
|
|
|
|
if (saved) {
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -1318,4 +1333,230 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
private void showToast(int resId, int duration) {
|
|
|
|
private void showToast(int resId, int duration) {
|
|
|
|
Toast.makeText(this, resId, duration).show();
|
|
|
|
Toast.makeText(this, resId, duration).show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @method convertToImage
|
|
|
|
|
|
|
|
* @description: 路径字符串格式 转换为 图片image格式
|
|
|
|
|
|
|
|
* @date: 2024/1/3 19:19
|
|
|
|
|
|
|
|
* @author: WuShuxian
|
|
|
|
|
|
|
|
* @param: void
|
|
|
|
|
|
|
|
* @return: void
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**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。算法效率有待改善可以考虑KMP
|
|
|
|
|
|
|
|
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个字符
|
|
|
|
|
|
|
|
int len = img_fragment.length()-15;//[local][/local]共15个字符,剩下的为真正的path长度
|
|
|
|
|
|
|
|
String path = img_fragment.substring(limit,limit+len);//获取到了图片路径从[local]之后的len个字符就是path
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
String ss = "[local]" + path + "[/local]";
|
|
|
|
|
|
|
|
SpannableString spannableString = new SpannableString(ss);//4.创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
spannableString.setSpan(imageSpan, 0, ss.length(),
|
|
|
|
|
|
|
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);//5.将指定的标记对象附加到文本的开始...结束范围
|
|
|
|
|
|
|
|
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.在路径的起始位置插入图片
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @method onActivityResult
|
|
|
|
|
|
|
|
* @description: 插入图片时:重写onActivityResult()来处理返回的数据,点击插入图片返回后执行
|
|
|
|
|
|
|
|
* @date: 2024/1/3 19:20
|
|
|
|
|
|
|
|
* @author: WuShuxian
|
|
|
|
|
|
|
|
* @param:
|
|
|
|
|
|
|
|
* @return: void
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**@Override
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//3.根据Bitmap对象创建ImageSpan对象
|
|
|
|
|
|
|
|
if(bitmap != null){
|
|
|
|
|
|
|
|
Log.d(TAG, "onActivityResult: bitmap is not null");
|
|
|
|
|
|
|
|
ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap);
|
|
|
|
|
|
|
|
String path = getPath(this,originalUri);
|
|
|
|
|
|
|
|
String img_fragment= "[local]" + path + "[/local]";//4.使用[local][/local]将path括起来,用于之后方便识别图片路径在note中的位置
|
|
|
|
|
|
|
|
SpannableString spannableString = new SpannableString(img_fragment);//创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像
|
|
|
|
|
|
|
|
spannableString.setSpan(imageSpan, 0,
|
|
|
|
|
|
|
|
img_fragment.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
|
|
|
|
|
|
|
NoteEditText e = (NoteEditText) findViewById(R.id.note_edit_view);//5.将选择的图片追加到EditText中光标所在位置
|
|
|
|
|
|
|
|
int index = e.getSelectionStart(); //获取光标所在位置
|
|
|
|
|
|
|
|
Log.d(TAG, "Index是: " + index);
|
|
|
|
|
|
|
|
Editable edit_text = e.getEditableText();
|
|
|
|
|
|
|
|
edit_text.insert(index, spannableString); //将图片插入到光标所在位置
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mWorkingNote.setWorkingText(e.getText().toString());
|
|
|
|
|
|
|
|
//6.把改动提交到数据库中,两个数据库表都要改的
|
|
|
|
|
|
|
|
ContentResolver contentResolver = getContentResolver();
|
|
|
|
|
|
|
|
ContentValues contentValues = new ContentValues();
|
|
|
|
|
|
|
|
final long id = mWorkingNote.getNoteId();
|
|
|
|
|
|
|
|
contentValues.put("snippet",mWorkingNote.getContent());
|
|
|
|
|
|
|
|
contentResolver.update(Uri.parse("content://micode_notes/note"),
|
|
|
|
|
|
|
|
contentValues,"_id=?",new String[]{""+id});
|
|
|
|
|
|
|
|
ContentValues contentValues1 = new ContentValues();
|
|
|
|
|
|
|
|
contentValues1.put("content",mWorkingNote.getContent());
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @method getPath
|
|
|
|
|
|
|
|
* @description: 获取文件的real path
|
|
|
|
|
|
|
|
* @date: 2024/1/3 19:22
|
|
|
|
|
|
|
|
* @author: WuShuxian
|
|
|
|
|
|
|
|
* @param:
|
|
|
|
|
|
|
|
* @return:
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**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)) {
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @method isMediaDocument
|
|
|
|
|
|
|
|
* @description: 判断是否为媒体文件
|
|
|
|
|
|
|
|
* @date: 2024/1/3 19:23
|
|
|
|
|
|
|
|
* @author: WuShuxian
|
|
|
|
|
|
|
|
* @param: uri
|
|
|
|
|
|
|
|
* @return:
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**public boolean isMediaDocument(Uri uri) {
|
|
|
|
|
|
|
|
return "com.android.providers.media.documents".equals(uri.getAuthority());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @method getDataColumn
|
|
|
|
|
|
|
|
* @description: 获取数据列_获取此 Uri 的数据列的值。这对MediaStore Uris 和其他基于文件的 ContentProvider。
|
|
|
|
|
|
|
|
* @date: 2024/1/3 19:23
|
|
|
|
|
|
|
|
* @author: WuShuxian
|
|
|
|
|
|
|
|
* @param:
|
|
|
|
|
|
|
|
* @return:
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**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;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @method checkStoragePermissions
|
|
|
|
|
|
|
|
* @description: 用于动态申请权限
|
|
|
|
|
|
|
|
* @date: 2024/1/6 8:58
|
|
|
|
|
|
|
|
* @author: WuShuxian
|
|
|
|
|
|
|
|
* @param: activity
|
|
|
|
|
|
|
|
* @return: void
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**public static void checkStoragePermissions(Activity activity){
|
|
|
|
|
|
|
|
try{
|
|
|
|
|
|
|
|
//监测是否有写/读的权限
|
|
|
|
|
|
|
|
int permission= ActivityCompat.checkSelfPermission(activity,
|
|
|
|
|
|
|
|
"android.permission.WRITE_EXTERNAL_STORAGE");
|
|
|
|
|
|
|
|
int permission1= ActivityCompat.checkSelfPermission(activity,
|
|
|
|
|
|
|
|
"android.permission.READ_EXTERNAL_STORAGE");
|
|
|
|
|
|
|
|
if(permission != PackageManager.PERMISSION_GRANTED){
|
|
|
|
|
|
|
|
//没有写的权限,去申请写的权限,或弹出对话框
|
|
|
|
|
|
|
|
ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(permission1 != PackageManager.PERMISSION_GRANTED){
|
|
|
|
|
|
|
|
//没有读的权限,去申请读的权限,或弹出对话框
|
|
|
|
|
|
|
|
ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}catch (Exception e){
|
|
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @method textToSpeach
|
|
|
|
|
|
|
|
* @description: 朗读功能
|
|
|
|
|
|
|
|
* @date: 2024/1/16 20:21
|
|
|
|
|
|
|
|
* @author: WuShuxian
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**private void textToSpeach(){
|
|
|
|
|
|
|
|
mTTS.speak(mNoteEditor.getText().toString(),TextToSpeech.QUEUE_FLUSH,null);
|
|
|
|
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|