diff --git a/src/Notes-master/res/layout/note_edit.xml b/src/Notes-master/res/layout/note_edit.xml index efc2bdc..abde9ae 100644 --- a/src/Notes-master/res/layout/note_edit.xml +++ b/src/Notes-master/res/layout/note_edit.xml @@ -56,11 +56,31 @@ android:layout_marginRight="8dip" android:textAppearance="@style/TextAppearanceSecondaryItem" /> + + + + + + 选择文件夹 上一级文件夹 已添加到桌面 + 图片插入成功 删除 确认要删除所选的 %d 条便签吗? 确认要删除该条便签吗? diff --git a/src/Notes-master/res/values/strings.xml b/src/Notes-master/res/values/strings.xml index fe6608c..170e4f0 100644 --- a/src/Notes-master/res/values/strings.xml +++ b/src/Notes-master/res/values/strings.xml @@ -75,6 +75,7 @@ Select folder Parent folder Note added to home + Image inserted successfully Confirm to delete folder and its notes? Delete selected notes Confirm to clear all notes from trash? This action cannot be undone. diff --git a/src/Notes-master/src/net/micode/notes/tool/DataUtils.java b/src/Notes-master/src/net/micode/notes/tool/DataUtils.java index 5cab067..8754e57 100644 --- a/src/Notes-master/src/net/micode/notes/tool/DataUtils.java +++ b/src/Notes-master/src/net/micode/notes/tool/DataUtils.java @@ -69,18 +69,18 @@ public class DataUtils { if (columnIndex >= 0) { int type = cursor.getType(columnIndex); switch (type) { - case android.database.Cursor.FIELD_TYPE_NULL: + case Cursor.FIELD_TYPE_NULL: break; - case android.database.Cursor.FIELD_TYPE_INTEGER: + case Cursor.FIELD_TYPE_INTEGER: trashValues.put(column, cursor.getLong(columnIndex)); break; - case android.database.Cursor.FIELD_TYPE_FLOAT: + case Cursor.FIELD_TYPE_FLOAT: trashValues.put(column, cursor.getDouble(columnIndex)); break; - case android.database.Cursor.FIELD_TYPE_STRING: + case Cursor.FIELD_TYPE_STRING: trashValues.put(column, cursor.getString(columnIndex)); break; - case android.database.Cursor.FIELD_TYPE_BLOB: + case Cursor.FIELD_TYPE_BLOB: trashValues.put(column, cursor.getBlob(columnIndex)); break; } @@ -312,18 +312,18 @@ public class DataUtils { if (columnIndex >= 0) { int type = cursor.getType(columnIndex); switch (type) { - case android.database.Cursor.FIELD_TYPE_NULL: + case Cursor.FIELD_TYPE_NULL: break; - case android.database.Cursor.FIELD_TYPE_INTEGER: + case Cursor.FIELD_TYPE_INTEGER: noteValues.put(column, cursor.getLong(columnIndex)); break; - case android.database.Cursor.FIELD_TYPE_FLOAT: + case Cursor.FIELD_TYPE_FLOAT: noteValues.put(column, cursor.getDouble(columnIndex)); break; - case android.database.Cursor.FIELD_TYPE_STRING: + case Cursor.FIELD_TYPE_STRING: noteValues.put(column, cursor.getString(columnIndex)); break; - case android.database.Cursor.FIELD_TYPE_BLOB: + case Cursor.FIELD_TYPE_BLOB: noteValues.put(column, cursor.getBlob(columnIndex)); break; } diff --git a/src/Notes-master/src/net/micode/notes/ui/NoteEditActivity.java b/src/Notes-master/src/net/micode/notes/ui/NoteEditActivity.java index 3b5788f..4d39639 100644 --- a/src/Notes-master/src/net/micode/notes/ui/NoteEditActivity.java +++ b/src/Notes-master/src/net/micode/notes/ui/NoteEditActivity.java @@ -51,6 +51,20 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; 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.data.Notes; @@ -142,6 +156,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, } private static final String TAG = "NoteEditActivity"; // 日志标签 + private static final int REQUEST_CODE_PICK_IMAGE = 100; // 图片选择请求码 OMO private HeadViewHolder mNoteHeaderHolder; // 头部视图持有者 private View mHeadViewPanel; // 头部视图面板 @@ -152,6 +167,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, private WorkingNote mWorkingNote; // 工作笔记对象 private SharedPreferences mSharedPrefs; // 共享偏好设置 private int mFontSizeId; // 字体大小ID + private ImageButton mBtnInsertImage; // 插入图片按钮 OMO private static final String PREFERENCE_FONT_SIZE = "pref_font_size"; // 字体大小偏好设置键 private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10; // 快捷图标标题最大长度 @@ -332,9 +348,14 @@ public class NoteEditActivity extends Activity implements OnClickListener, switchToListMode(mWorkingNote.getContent()); // 切换到清单模式 } 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(); // 显示提醒头部 } + /** + * 将包含[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); + + // 初始化插入图片按钮 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)); } 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 带有高亮效果的文本 */ 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)) { mPattern = Pattern.compile(userQuery); // 编译正则表达式 - Matcher m = mPattern.matcher(fullText); // 创建匹配器 + Matcher m = mPattern.matcher(text); // 创建匹配器 int start = 0; while (m.find(start)) { // 设置高亮背景色 @@ -924,6 +1036,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, start = m.end(); } } + return spannable; } @@ -1139,4 +1252,50 @@ public class NoteEditActivity extends Activity implements OnClickListener, private void showToast(int resId, int duration) { 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); + } + } } diff --git a/src/Notes-master/src/net/micode/notes/ui/NoteItemData.java b/src/Notes-master/src/net/micode/notes/ui/NoteItemData.java index bdaaf28..ef52f3f 100644 --- a/src/Notes-master/src/net/micode/notes/ui/NoteItemData.java +++ b/src/Notes-master/src/net/micode/notes/ui/NoteItemData.java @@ -36,19 +36,19 @@ import net.micode.notes.tool.DataUtils; public class NoteItemData { /** 数据库查询投影数组 */ static final String [] PROJECTION = new String [] { - NoteColumns.ID, // 笔记ID - NoteColumns.ALERTED_DATE, // 提醒日期 - NoteColumns.BG_COLOR_ID, // 背景颜色ID - NoteColumns.CREATED_DATE, // 创建日期 - NoteColumns.HAS_ATTACHMENT, // 是否有附件 - NoteColumns.MODIFIED_DATE, // 修改日期 - NoteColumns.NOTES_COUNT, // 笔记数量 - NoteColumns.PARENT_ID, // 父文件夹ID - NoteColumns.SNIPPET, // 笔记摘要 - NoteColumns.TYPE, // 笔记类型 - NoteColumns.WIDGET_ID, // 小部件ID - NoteColumns.WIDGET_TYPE, // 小部件类型 - NoteColumns.IS_ENCRYPTED, // 是否加密 + NoteColumns.ID, // 笔记ID + NoteColumns.ALERTED_DATE, // 提醒日期 + NoteColumns.BG_COLOR_ID, // 背景颜色ID + NoteColumns.CREATED_DATE, // 创建日期 + NoteColumns.HAS_ATTACHMENT, // 是否有附件 + NoteColumns.MODIFIED_DATE, // 修改日期 + NoteColumns.NOTES_COUNT, // 笔记数量 + NoteColumns.PARENT_ID, // 父文件夹ID + NoteColumns.SNIPPET, // 笔记摘要 + NoteColumns.TYPE, // 笔记类型 + NoteColumns.WIDGET_ID, // 小部件ID + NoteColumns.WIDGET_TYPE, // 小部件类型 + NoteColumns.IS_ENCRYPTED, // 是否加密 }; /** 笔记ID列索引 */ diff --git a/src/Notes-master/src/net/micode/notes/ui/NotesListActivity.java b/src/Notes-master/src/net/micode/notes/ui/NotesListActivity.java index c6210b4..5277d75 100644 --- a/src/Notes-master/src/net/micode/notes/ui/NotesListActivity.java +++ b/src/Notes-master/src/net/micode/notes/ui/NotesListActivity.java @@ -17,6 +17,7 @@ package net.micode.notes.ui; import android.app.Activity; +import net.micode.notes.ui.PasswordInputActivity; import android.app.AlertDialog; import android.app.Dialog; import android.appwidget.AppWidgetManager; @@ -274,10 +275,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt mNoteModeButton = (Button) findViewById(R.id.btn_note_mode); mChecklistModeButton = (Button) findViewById(R.id.btn_checklist_mode); mIsChecklistMode = false; - // 只有当按钮存在时才更新状态,避免空指针异常 - if (mNoteModeButton != null && mChecklistModeButton != null) { - updateModeButtons(); - } + updateModeButtons(); mChecklistManager = new ChecklistManager(mContentResolver); } @@ -836,21 +834,18 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt * OMO */ private void updateModeButtons() { - // 确保按钮不为空,避免空指针异常 - if (mNoteModeButton != null && mChecklistModeButton != null) { - if (mIsChecklistMode) { - // 清单模式下,清单按钮高亮 - mChecklistModeButton.setBackgroundColor(0xFF007AFF); - mChecklistModeButton.setTextColor(0xFFFFFFFF); - mNoteModeButton.setBackgroundColor(0xFFFFFFFF); - mNoteModeButton.setTextColor(0xFF000000); - } else { - // 笔记模式下,笔记按钮高亮 - mNoteModeButton.setBackgroundColor(0xFF007AFF); - mNoteModeButton.setTextColor(0xFFFFFFFF); - mChecklistModeButton.setBackgroundColor(0xFFFFFFFF); - mChecklistModeButton.setTextColor(0xFF000000); - } + if (mIsChecklistMode) { + // 清单模式下,清单按钮高亮 + mChecklistModeButton.setBackgroundColor(0xFF007AFF); + mChecklistModeButton.setTextColor(0xFFFFFFFF); + mNoteModeButton.setBackgroundColor(0xFFFFFFFF); + mNoteModeButton.setTextColor(0xFF000000); + } else { + // 笔记模式下,笔记按钮高亮 + mNoteModeButton.setBackgroundColor(0xFF007AFF); + mNoteModeButton.setTextColor(0xFFFFFFFF); + mChecklistModeButton.setBackgroundColor(0xFFFFFFFF); + mChecklistModeButton.setTextColor(0xFF000000); } } @@ -1033,7 +1028,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt private void updateWidget(int appWidgetId, int appWidgetType) { Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); if (appWidgetType == Notes.TYPE_WIDGET_2X) { - intent.setClass(this, NoteWidgetProvider_2x.class); + intent.setClass(this,NoteWidgetProvider_2x.class); } else if (appWidgetType == Notes.TYPE_WIDGET_4X) { intent.setClass(this, NoteWidgetProvider_4x.class); } else { diff --git a/src/Notes-master/src/net/micode/notes/ui/NotesListItem.java b/src/Notes-master/src/net/micode/notes/ui/NotesListItem.java index 12107ab..46c35f0 100644 --- a/src/Notes-master/src/net/micode/notes/ui/NotesListItem.java +++ b/src/Notes-master/src/net/micode/notes/ui/NotesListItem.java @@ -257,7 +257,7 @@ public class NotesListItem extends LinearLayout { // 添加长按事件,长按后可编辑 mChecklistTitle.setLongClickable(true); - mChecklistTitle.setOnLongClickListener(new View.OnLongClickListener() { + mChecklistTitle.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { // 设置为可编辑状态 @@ -281,7 +281,7 @@ public class NotesListItem extends LinearLayout { }); // 添加焦点变化监听器,失去焦点时保存修改并恢复为不可编辑状态 - mChecklistTitle.setOnFocusChangeListener(new View.OnFocusChangeListener() { + mChecklistTitle.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) {