Merge pull request '新增图片插入,解决图片插入功能疑修' (#18) from wangjiaqi_branch into master

pull/19/head
p82feo7wg 2 months ago
commit d954ca92eb

@ -56,11 +56,31 @@
android:layout_marginRight="8dip"
android:textAppearance="@style/TextAppearanceSecondaryItem" />
<!-- 插入图片按钮 -->
<ImageButton
android:id="@+id/btn_insert_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@android:drawable/ic_menu_gallery"
android:background="@drawable/bg_btn_set_color"
android:layout_marginRight="8dip" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/bg_btn_set_color" />
<!-- Insert image button OMO -->
<ImageButton
android:id="@+id/btn_insert_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@android:drawable/ic_menu_gallery"
android:background="@drawable/bg_btn_set_color"
android:layout_marginLeft="8dip" />
</LinearLayout>
<LinearLayout

@ -71,6 +71,7 @@
<string name="menu_title_select_folder">选择文件夹</string>
<string name="menu_move_parent_folder">上一级文件夹</string>
<string name="info_note_enter_desktop">已添加到桌面</string>
<string name="info_image_inserted">图片插入成功</string> <!-- OMO -->
<string name="alert_title_delete">删除</string>
<string name="alert_message_delete_notes">确认要删除所选的 %d 条便签吗?</string>
<string name="alert_message_delete_note">确认要删除该条便签吗?</string>

@ -75,6 +75,7 @@
<string name="menu_title_select_folder">Select folder</string>
<string name="menu_move_parent_folder">Parent folder</string>
<string name="info_note_enter_desktop">Note added to home</string>
<string name="info_image_inserted">Image inserted successfully</string> <!-- OMO -->
<string name="alert_message_delete_folder">Confirm to delete folder and its notes?</string>
<string name="alert_title_delete">Delete selected notes</string>
<string name="alert_message_clear_all_trash">Confirm to clear all notes from trash? This action cannot be undone.</string>

@ -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;
}

@ -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]ImageSpanSpannableString
* @param text [IMAGE]
* @return ImageSpanSpannableString
*/
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);
}
}
}

@ -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列索引 */

@ -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 {

@ -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) {

Loading…
Cancel
Save