|
|
|
@ -51,6 +51,20 @@ import android.widget.ImageView;
|
|
|
|
import android.widget.LinearLayout;
|
|
|
|
import android.widget.LinearLayout;
|
|
|
|
import android.widget.TextView;
|
|
|
|
import android.widget.TextView;
|
|
|
|
import android.widget.Toast;
|
|
|
|
import android.widget.Toast;
|
|
|
|
|
|
|
|
import android.widget.ImageButton;
|
|
|
|
|
|
|
|
import android.provider.MediaStore;
|
|
|
|
|
|
|
|
import android.net.Uri;
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
|
|
|
import android.text.SpannableString;
|
|
|
|
|
|
|
|
import android.text.SpannableStringBuilder;
|
|
|
|
|
|
|
|
import android.text.Editable;
|
|
|
|
|
|
|
|
import android.text.style.ImageSpan;
|
|
|
|
|
|
|
|
import android.graphics.drawable.Drawable;
|
|
|
|
|
|
|
|
import android.content.ContentResolver;
|
|
|
|
|
|
|
|
import android.content.res.Resources;
|
|
|
|
|
|
|
|
import android.graphics.Bitmap;
|
|
|
|
|
|
|
|
import android.graphics.BitmapFactory;
|
|
|
|
|
|
|
|
import java.io.InputStream;
|
|
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.R;
|
|
|
|
import net.micode.notes.R;
|
|
|
|
import net.micode.notes.data.Notes;
|
|
|
|
import net.micode.notes.data.Notes;
|
|
|
|
@ -142,6 +156,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static final String TAG = "NoteEditActivity"; // 日志标签
|
|
|
|
private static final String TAG = "NoteEditActivity"; // 日志标签
|
|
|
|
|
|
|
|
private static final int REQUEST_CODE_PICK_IMAGE = 100; // 图片选择请求码 OMO
|
|
|
|
|
|
|
|
|
|
|
|
private HeadViewHolder mNoteHeaderHolder; // 头部视图持有者
|
|
|
|
private HeadViewHolder mNoteHeaderHolder; // 头部视图持有者
|
|
|
|
private View mHeadViewPanel; // 头部视图面板
|
|
|
|
private View mHeadViewPanel; // 头部视图面板
|
|
|
|
@ -152,6 +167,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
private WorkingNote mWorkingNote; // 工作笔记对象
|
|
|
|
private WorkingNote mWorkingNote; // 工作笔记对象
|
|
|
|
private SharedPreferences mSharedPrefs; // 共享偏好设置
|
|
|
|
private SharedPreferences mSharedPrefs; // 共享偏好设置
|
|
|
|
private int mFontSizeId; // 字体大小ID
|
|
|
|
private int mFontSizeId; // 字体大小ID
|
|
|
|
|
|
|
|
private ImageButton mBtnInsertImage; // 插入图片按钮 OMO
|
|
|
|
|
|
|
|
|
|
|
|
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; // 快捷图标标题最大长度
|
|
|
|
@ -332,9 +348,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
switchToListMode(mWorkingNote.getContent()); // 切换到清单模式
|
|
|
|
switchToListMode(mWorkingNote.getContent()); // 切换到清单模式
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// 设置笔记内容并高亮查询结果
|
|
|
|
// 设置笔记内容并高亮查询结果
|
|
|
|
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
|
|
|
|
String content = mWorkingNote.getContent();
|
|
|
|
|
|
|
|
Log.d(TAG, "Initializing note content: " + content);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 将文本内容转换为包含ImageSpan的SpannableString
|
|
|
|
|
|
|
|
SpannableString spannableString = convertTextToSpannableWithImages(content);
|
|
|
|
|
|
|
|
mNoteEditor.setText(spannableString);
|
|
|
|
// 将光标定位到文本末尾
|
|
|
|
// 将光标定位到文本末尾
|
|
|
|
mNoteEditor.setSelection(mNoteEditor.getText().length());
|
|
|
|
mNoteEditor.setSelection(spannableString.length());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 隐藏所有背景选择的选中状态
|
|
|
|
// 隐藏所有背景选择的选中状态
|
|
|
|
@ -359,6 +380,85 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
showAlertHeader(); // 显示提醒头部
|
|
|
|
showAlertHeader(); // 显示提醒头部
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 将包含[IMAGE]标签的文本转换为包含ImageSpan的SpannableString
|
|
|
|
|
|
|
|
* @param text 包含[IMAGE]标签的文本
|
|
|
|
|
|
|
|
* @return 包含ImageSpan的SpannableString
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private SpannableString convertTextToSpannableWithImages(String text) {
|
|
|
|
|
|
|
|
if (TextUtils.isEmpty(text)) {
|
|
|
|
|
|
|
|
return new SpannableString("");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建一个新的SpannableStringBuilder
|
|
|
|
|
|
|
|
SpannableStringBuilder builder = new SpannableStringBuilder();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 查找所有[IMAGE]标签
|
|
|
|
|
|
|
|
int startIndex = 0;
|
|
|
|
|
|
|
|
int imageStart = text.indexOf("[IMAGE]", startIndex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (imageStart != -1) {
|
|
|
|
|
|
|
|
// 添加[IMAGE]标签之前的文本
|
|
|
|
|
|
|
|
builder.append(text.substring(startIndex, imageStart));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 查找当前[IMAGE]标签的结束位置
|
|
|
|
|
|
|
|
int imageEnd = text.indexOf("[/IMAGE]", imageStart + "[IMAGE]".length());
|
|
|
|
|
|
|
|
if (imageEnd == -1) {
|
|
|
|
|
|
|
|
// 如果没有找到结束标签,添加剩余文本并退出循环
|
|
|
|
|
|
|
|
builder.append(text.substring(imageStart));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 提取图片URI
|
|
|
|
|
|
|
|
String imageUri = text.substring(imageStart + "[IMAGE]".length(), imageEnd);
|
|
|
|
|
|
|
|
Log.d(TAG, "Found image URI: " + imageUri);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建一个占位符字符串,用于插入ImageSpan
|
|
|
|
|
|
|
|
String placeholder = " ";
|
|
|
|
|
|
|
|
int placeholderStart = builder.length();
|
|
|
|
|
|
|
|
builder.append(placeholder);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 尝试将图片URI转换为Drawable并创建ImageSpan
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
ContentResolver resolver = getContentResolver();
|
|
|
|
|
|
|
|
InputStream inputStream = resolver.openInputStream(Uri.parse(imageUri));
|
|
|
|
|
|
|
|
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
|
|
|
|
|
|
|
inputStream.close();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算图片的合适大小,确保它能适应EditText的宽度
|
|
|
|
|
|
|
|
int screenWidth = getResources().getDisplayMetrics().widthPixels;
|
|
|
|
|
|
|
|
int imageWidth = bitmap.getWidth();
|
|
|
|
|
|
|
|
int imageHeight = bitmap.getHeight();
|
|
|
|
|
|
|
|
float scale = (float) screenWidth / (float) imageWidth;
|
|
|
|
|
|
|
|
int scaledHeight = (int) (imageHeight * scale);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 缩放图片
|
|
|
|
|
|
|
|
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, screenWidth, scaledHeight, true);
|
|
|
|
|
|
|
|
Drawable drawable = new android.graphics.drawable.BitmapDrawable(getResources(), scaledBitmap);
|
|
|
|
|
|
|
|
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建ImageSpan并添加到SpannableStringBuilder中
|
|
|
|
|
|
|
|
ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
|
|
|
|
|
|
|
|
builder.setSpan(imageSpan, placeholderStart, placeholderStart + placeholder.length(), SpannableString.SPAN_INCLUSIVE_EXCLUSIVE);
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
Log.e(TAG, "Error loading image: " + e.toString());
|
|
|
|
|
|
|
|
// 如果加载图片失败,直接显示图片URI
|
|
|
|
|
|
|
|
builder.append("[IMAGE]");
|
|
|
|
|
|
|
|
builder.append(imageUri);
|
|
|
|
|
|
|
|
builder.append("[/IMAGE]");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新索引,继续查找下一个[IMAGE]标签
|
|
|
|
|
|
|
|
startIndex = imageEnd + "[/IMAGE]".length();
|
|
|
|
|
|
|
|
imageStart = text.indexOf("[IMAGE]", startIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 添加剩余的文本
|
|
|
|
|
|
|
|
builder.append(text.substring(startIndex));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new SpannableString(builder);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* 显示提醒头部
|
|
|
|
* 显示提醒头部
|
|
|
|
* 根据笔记的提醒设置显示或隐藏提醒信息
|
|
|
|
* 根据笔记的提醒设置显示或隐藏提醒信息
|
|
|
|
@ -491,6 +591,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
|
|
|
|
mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化插入图片按钮 OMO
|
|
|
|
|
|
|
|
mBtnInsertImage = (ImageButton) findViewById(R.id.btn_insert_image);
|
|
|
|
|
|
|
|
if (mBtnInsertImage != null) {
|
|
|
|
|
|
|
|
mBtnInsertImage.setOnClickListener(this);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@ -565,6 +671,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
|
|
|
|
TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mFontSizeSelector.setVisibility(View.GONE);
|
|
|
|
mFontSizeSelector.setVisibility(View.GONE);
|
|
|
|
|
|
|
|
} else if (id == R.id.btn_insert_image) {
|
|
|
|
|
|
|
|
// 处理插入图片按钮点击事件 OMO
|
|
|
|
|
|
|
|
pickImageFromGallery();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -910,10 +1019,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
* @return 带有高亮效果的文本
|
|
|
|
* @return 带有高亮效果的文本
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private Spannable getHighlightQueryResult(String fullText, String userQuery) {
|
|
|
|
private Spannable getHighlightQueryResult(String fullText, String userQuery) {
|
|
|
|
SpannableString spannable = new SpannableString(fullText == null ? "" : fullText);
|
|
|
|
String text = fullText == null ? "" : fullText;
|
|
|
|
|
|
|
|
SpannableString spannable = new SpannableString(text);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 处理查询关键词高亮
|
|
|
|
if (!TextUtils.isEmpty(userQuery)) {
|
|
|
|
if (!TextUtils.isEmpty(userQuery)) {
|
|
|
|
mPattern = Pattern.compile(userQuery); // 编译正则表达式
|
|
|
|
mPattern = Pattern.compile(userQuery); // 编译正则表达式
|
|
|
|
Matcher m = mPattern.matcher(fullText); // 创建匹配器
|
|
|
|
Matcher m = mPattern.matcher(text); // 创建匹配器
|
|
|
|
int start = 0;
|
|
|
|
int start = 0;
|
|
|
|
while (m.find(start)) {
|
|
|
|
while (m.find(start)) {
|
|
|
|
// 设置高亮背景色
|
|
|
|
// 设置高亮背景色
|
|
|
|
@ -924,6 +1036,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
start = m.end();
|
|
|
|
start = m.end();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return spannable;
|
|
|
|
return spannable;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1139,4 +1252,50 @@ 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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 从相册选择图片 OMO
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private void pickImageFromGallery() {
|
|
|
|
|
|
|
|
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
|
|
|
|
|
|
|
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 处理图片选择结果 OMO
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
|
|
|
|
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
|
|
|
|
|
|
if (requestCode == REQUEST_CODE_PICK_IMAGE && resultCode == RESULT_OK && data != null) {
|
|
|
|
|
|
|
|
Log.d(TAG, "Image selected successfully, data: " + data.toString());
|
|
|
|
|
|
|
|
Uri imageUri = data.getData();
|
|
|
|
|
|
|
|
if (imageUri != null) {
|
|
|
|
|
|
|
|
Log.d(TAG, "Image URI: " + imageUri.toString());
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
// 将图片路径添加到笔记内容中
|
|
|
|
|
|
|
|
String currentContent = mNoteEditor.getText().toString();
|
|
|
|
|
|
|
|
String imagePath = "[IMAGE]" + imageUri.toString() + "[/IMAGE]";
|
|
|
|
|
|
|
|
String newContent = currentContent + (currentContent.isEmpty() ? "" : "\n") + imagePath;
|
|
|
|
|
|
|
|
Log.d(TAG, "New content: " + newContent);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 直接设置文本,不使用ImageSpan,这样可以确保内容被保存
|
|
|
|
|
|
|
|
mNoteEditor.setText(newContent);
|
|
|
|
|
|
|
|
mNoteEditor.setSelection(newContent.length());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 保存笔记内容,确保图片路径被正确存储
|
|
|
|
|
|
|
|
saveNote();
|
|
|
|
|
|
|
|
showToast(R.string.info_image_inserted);
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
Log.e(TAG, "Error inserting image: " + e.toString());
|
|
|
|
|
|
|
|
showToast(R.string.error_note_not_exist);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
Log.e(TAG, "Image URI is null");
|
|
|
|
|
|
|
|
showToast(R.string.error_note_not_exist);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
Log.d(TAG, "Image selection canceled or failed, resultCode: " + resultCode);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|