|
|
|
|
@ -27,11 +27,16 @@ import android.content.Context;
|
|
|
|
|
import android.content.DialogInterface;
|
|
|
|
|
import android.content.Intent;
|
|
|
|
|
import android.content.SharedPreferences;
|
|
|
|
|
import android.content.pm.PackageManager;
|
|
|
|
|
import android.graphics.Paint;
|
|
|
|
|
import android.net.Uri;
|
|
|
|
|
import android.os.Build;
|
|
|
|
|
import android.os.Bundle;
|
|
|
|
|
import android.preference.PreferenceManager;
|
|
|
|
|
import android.provider.MediaStore;
|
|
|
|
|
import android.text.Spannable;
|
|
|
|
|
import android.text.SpannableString;
|
|
|
|
|
import android.text.SpannableStringBuilder;
|
|
|
|
|
import android.text.TextUtils;
|
|
|
|
|
import android.text.format.DateUtils;
|
|
|
|
|
import android.text.style.BackgroundColorSpan;
|
|
|
|
|
@ -47,23 +52,19 @@ 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 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.Typeface;
|
|
|
|
|
import android.graphics.Bitmap;
|
|
|
|
|
import android.graphics.BitmapFactory;
|
|
|
|
|
import android.graphics.drawable.Drawable;
|
|
|
|
|
import android.content.ContentResolver;
|
|
|
|
|
import android.content.res.Resources;
|
|
|
|
|
import android.graphics.Bitmap;
|
|
|
|
|
import android.graphics.BitmapFactory;
|
|
|
|
|
// import android.support.annotation.NonNull;
|
|
|
|
|
import android.Manifest;
|
|
|
|
|
import android.graphics.Color;
|
|
|
|
|
import java.io.InputStream;
|
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
|
@ -443,6 +444,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
return new SpannableString("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Log.d(TAG, "Converting text to Spannable with images: " + text);
|
|
|
|
|
|
|
|
|
|
// 创建一个新的SpannableStringBuilder
|
|
|
|
|
SpannableStringBuilder builder = new SpannableStringBuilder();
|
|
|
|
|
|
|
|
|
|
@ -451,6 +454,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
int imageStart = text.indexOf("[IMAGE]", startIndex);
|
|
|
|
|
|
|
|
|
|
while (imageStart != -1) {
|
|
|
|
|
Log.d(TAG, "Found [IMAGE] tag at position: " + imageStart);
|
|
|
|
|
|
|
|
|
|
// 添加[IMAGE]标签之前的文本
|
|
|
|
|
builder.append(text.substring(startIndex, imageStart));
|
|
|
|
|
|
|
|
|
|
@ -462,43 +467,97 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Log.d(TAG, "Found [/IMAGE] tag at position: " + imageEnd);
|
|
|
|
|
|
|
|
|
|
// 提取图片URI
|
|
|
|
|
String imageUri = text.substring(imageStart + "[IMAGE]".length(), imageEnd);
|
|
|
|
|
Log.d(TAG, "Found image URI: " + imageUri);
|
|
|
|
|
Log.d(TAG, "Extracted image URI: " + imageUri);
|
|
|
|
|
|
|
|
|
|
// 创建一个占位符字符串,用于插入ImageSpan
|
|
|
|
|
String placeholder = " ";
|
|
|
|
|
int placeholderStart = builder.length();
|
|
|
|
|
builder.append(placeholder);
|
|
|
|
|
// 保留原始的[IMAGE]uri[/IMAGE]标签,直接在上面添加ImageSpan
|
|
|
|
|
String fullImageTag = "[IMAGE]" + imageUri + "[/IMAGE]";
|
|
|
|
|
int tagStart = builder.length();
|
|
|
|
|
builder.append(fullImageTag);
|
|
|
|
|
|
|
|
|
|
// 尝试将图片URI转换为Drawable并创建ImageSpan
|
|
|
|
|
try {
|
|
|
|
|
// 确保URI是有效的
|
|
|
|
|
Uri uri = Uri.parse(imageUri);
|
|
|
|
|
if (uri == null) {
|
|
|
|
|
Log.e(TAG, "Invalid URI: " + imageUri);
|
|
|
|
|
// 更新索引,继续处理下一个标签
|
|
|
|
|
startIndex = imageEnd + "[/IMAGE]".length();
|
|
|
|
|
imageStart = text.indexOf("[IMAGE]", startIndex);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Log.d(TAG, "Attempting to load image from URI: " + uri.toString());
|
|
|
|
|
|
|
|
|
|
// 使用BitmapFactory直接加载图片,这是最可靠的方式
|
|
|
|
|
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);
|
|
|
|
|
InputStream inputStream = null;
|
|
|
|
|
try {
|
|
|
|
|
inputStream = resolver.openInputStream(uri);
|
|
|
|
|
if (inputStream == null) {
|
|
|
|
|
Log.e(TAG, "Failed to open input stream for URI: " + uri.toString());
|
|
|
|
|
// 更新索引,继续处理下一个标签
|
|
|
|
|
startIndex = imageEnd + "[/IMAGE]".length();
|
|
|
|
|
imageStart = text.indexOf("[IMAGE]", startIndex);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解码图片
|
|
|
|
|
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
|
|
|
|
if (bitmap == null) {
|
|
|
|
|
Log.e(TAG, "Failed to decode bitmap from URI: " + uri.toString());
|
|
|
|
|
// 更新索引,继续处理下一个标签
|
|
|
|
|
startIndex = imageEnd + "[/IMAGE]".length();
|
|
|
|
|
imageStart = text.indexOf("[IMAGE]", startIndex);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Log.d(TAG, "Successfully decoded bitmap with dimensions: " + bitmap.getWidth() + "x" + bitmap.getHeight());
|
|
|
|
|
|
|
|
|
|
// 计算图片的合适大小,确保它能适应EditText的宽度
|
|
|
|
|
int screenWidth = getResources().getDisplayMetrics().widthPixels;
|
|
|
|
|
// 减去左右边距,确保图片能完整显示
|
|
|
|
|
int maxWidth = screenWidth - 40;
|
|
|
|
|
int imageWidth = bitmap.getWidth();
|
|
|
|
|
int imageHeight = bitmap.getHeight();
|
|
|
|
|
|
|
|
|
|
// 计算缩放比例
|
|
|
|
|
float scale = 1.0f;
|
|
|
|
|
if (imageWidth > maxWidth) {
|
|
|
|
|
scale = (float) maxWidth / (float) imageWidth;
|
|
|
|
|
}
|
|
|
|
|
Log.d(TAG, "Calculated scale: " + scale);
|
|
|
|
|
|
|
|
|
|
// 缩放图片(如果需要)
|
|
|
|
|
if (scale < 1.0f) {
|
|
|
|
|
bitmap = Bitmap.createScaledBitmap(bitmap, (int)(imageWidth * scale), (int)(imageHeight * scale), true);
|
|
|
|
|
Log.d(TAG, "Scaled bitmap to: " + bitmap.getWidth() + "x" + bitmap.getHeight());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建Drawable并设置边界
|
|
|
|
|
Drawable drawable = new android.graphics.drawable.BitmapDrawable(getResources(), bitmap);
|
|
|
|
|
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
|
|
|
|
|
|
|
|
|
|
// 创建ImageSpan并添加到SpannableStringBuilder中
|
|
|
|
|
ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
|
|
|
|
|
builder.setSpan(imageSpan, tagStart, tagStart + fullImageTag.length(), SpannableString.SPAN_INCLUSIVE_EXCLUSIVE);
|
|
|
|
|
Log.d(TAG, "Successfully added ImageSpan for URI: " + imageUri);
|
|
|
|
|
} finally {
|
|
|
|
|
// 确保InputStream被正确关闭
|
|
|
|
|
if (inputStream != null) {
|
|
|
|
|
try {
|
|
|
|
|
inputStream.close();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
Log.e(TAG, "Error closing input stream: " + e.toString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
Log.e(TAG, "Error loading image: " + e.toString());
|
|
|
|
|
// 如果加载图片失败,直接显示图片URI
|
|
|
|
|
builder.append("[IMAGE]");
|
|
|
|
|
builder.append(imageUri);
|
|
|
|
|
builder.append("[/IMAGE]");
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新索引,继续查找下一个[IMAGE]标签
|
|
|
|
|
@ -509,6 +568,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
// 添加剩余的文本
|
|
|
|
|
builder.append(text.substring(startIndex));
|
|
|
|
|
|
|
|
|
|
Log.d(TAG, "Final SpannableStringBuilder content: " + builder.toString());
|
|
|
|
|
return new SpannableString(builder);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -679,7 +739,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
if (mBtnInsertImage != null) {
|
|
|
|
|
mBtnInsertImage.setOnClickListener(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化富文本功能按钮
|
|
|
|
|
initRichEditorButtons();
|
|
|
|
|
}
|
|
|
|
|
@ -1368,6 +1428,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
/**
|
|
|
|
|
* 从相册选择图片 OMO
|
|
|
|
|
*/
|
|
|
|
|
private static final int REQUEST_CODE_PERMISSION_STORAGE = 101;
|
|
|
|
|
|
|
|
|
|
private void pickImageFromGallery() {
|
|
|
|
|
try {
|
|
|
|
|
// 意图:打开系统相册选择图片
|
|
|
|
|
@ -1387,6 +1449,21 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理权限请求结果
|
|
|
|
|
@Override
|
|
|
|
|
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
|
|
|
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
|
|
|
if (requestCode == REQUEST_CODE_PERMISSION_STORAGE) {
|
|
|
|
|
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
|
|
|
|
// 权限被授予,执行图片选择
|
|
|
|
|
pickImageFromGallery();
|
|
|
|
|
} else {
|
|
|
|
|
// 权限被拒绝,显示提示
|
|
|
|
|
showToast(R.string.error_permission_denied);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理图片选择结果 OMO
|
|
|
|
|
*/
|
|
|
|
|
|