|
|
|
|
@ -105,6 +105,7 @@ import net.micode.notes.model.WorkingNote.NoteSettingChangedListener;
|
|
|
|
|
import net.micode.notes.tool.DataUtils;
|
|
|
|
|
import net.micode.notes.tool.ResourceParser;
|
|
|
|
|
import net.micode.notes.tool.ResourceParser.TextAppearanceResources;
|
|
|
|
|
import net.micode.notes.tool.BackgroundManager;
|
|
|
|
|
import net.micode.notes.ui.DateTimePickerDialog.OnDateTimeSetListener;
|
|
|
|
|
import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
|
|
|
|
|
import net.micode.notes.widget.NoteWidgetProvider_2x;
|
|
|
|
|
@ -140,6 +141,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
sBgSelectorBtnsMap.put(R.id.iv_bg_blue, ResourceParser.BLUE);
|
|
|
|
|
sBgSelectorBtnsMap.put(R.id.iv_bg_green, ResourceParser.GREEN);
|
|
|
|
|
sBgSelectorBtnsMap.put(R.id.iv_bg_white, ResourceParser.WHITE);
|
|
|
|
|
sBgSelectorBtnsMap.put(R.id.iv_bg_custom, -1); // 自定义背景
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -153,6 +155,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
sBgSelectorSelectionMap.put(ResourceParser.BLUE, R.id.iv_bg_blue_select);
|
|
|
|
|
sBgSelectorSelectionMap.put(ResourceParser.GREEN, R.id.iv_bg_green_select);
|
|
|
|
|
sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select);
|
|
|
|
|
sBgSelectorSelectionMap.put(-1, R.id.iv_bg_custom_select); // 自定义背景
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -180,8 +183,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static final String TAG = "NoteEditActivity"; // 日志标签
|
|
|
|
|
private static final int REQUEST_CODE_PICK_IMAGE = 100; // 图片选择请求码 OMO
|
|
|
|
|
private static final int PHOTO_REQUEST = 100; // 请求照片
|
|
|
|
|
private static final int REQUEST_CODE_PICK_IMAGE = 100; // 插入图片请求码
|
|
|
|
|
private static final int REQUEST_CODE_PICK_BACKGROUND = 101; // 背景图片请求码
|
|
|
|
|
private static final int PHOTO_REQUEST = REQUEST_CODE_PICK_IMAGE; // 保持兼容性
|
|
|
|
|
|
|
|
|
|
private HeadViewHolder mNoteHeaderHolder; // 头部视图持有者
|
|
|
|
|
private View mHeadViewPanel; // 头部视图面板
|
|
|
|
|
@ -193,7 +197,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
private WorkingNote mWorkingNote; // 工作笔记对象
|
|
|
|
|
private SharedPreferences mSharedPrefs; // 共享偏好设置
|
|
|
|
|
private int mFontSizeId; // 字体大小ID
|
|
|
|
|
private ImageButton mBtnInsertImage; // 插入图片按钮 OMO
|
|
|
|
|
private ImageButton mBtnInsertImage; // 插入图片按钮
|
|
|
|
|
private BackgroundManager mBackgroundManager; // 背景管理器
|
|
|
|
|
private String mText; // 用于存储富文本内容
|
|
|
|
|
private int mNoteLength; // 文本长度
|
|
|
|
|
|
|
|
|
|
@ -207,7 +212,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
private String mUserQuery; // 用户查询字符串
|
|
|
|
|
private Pattern mPattern; // 正则表达式模式(用于高亮查询结果)
|
|
|
|
|
private ChecklistManager mChecklistManager; // 清单管理器(OMO)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 标签管理相关控件
|
|
|
|
|
private LinearLayout mTagManagementSection; // 标签管理区域
|
|
|
|
|
private LinearLayout mExistingTagsContainer; // 现有标签容器
|
|
|
|
|
@ -215,7 +220,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
private EditText mTagInput; // 标签输入框
|
|
|
|
|
private Button mAddTagButton; // 添加标签按钮
|
|
|
|
|
private ArrayList<String> mTagsList; // 标签列表
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 搜索历史相关
|
|
|
|
|
private static final String PREFERENCE_SEARCH_HISTORY = "search_history"; // 搜索历史偏好设置键
|
|
|
|
|
private static final int MAX_SEARCH_HISTORY = 20; // 最大搜索历史记录数
|
|
|
|
|
@ -296,7 +301,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 保存搜索历史
|
|
|
|
|
if (!TextUtils.isEmpty(mUserQuery)) {
|
|
|
|
|
saveSearchHistory(mUserQuery);
|
|
|
|
|
@ -514,9 +519,22 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置头部视图和编辑器面板的背景
|
|
|
|
|
// 加载自定义背景图片
|
|
|
|
|
String backgroundPath = mWorkingNote.getCustomBackgroundPath();
|
|
|
|
|
if (backgroundPath != null && !backgroundPath.isEmpty()) {
|
|
|
|
|
Drawable background = mBackgroundManager.loadBackground(backgroundPath);
|
|
|
|
|
if (background != null) {
|
|
|
|
|
mNoteEditorPanel.setBackground(background);
|
|
|
|
|
} else {
|
|
|
|
|
// 如果背景图片加载失败,使用默认背景颜色
|
|
|
|
|
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 如果没有自定义背景,使用默认背景颜色
|
|
|
|
|
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
|
|
|
|
|
}
|
|
|
|
|
// 设置头部视图的背景
|
|
|
|
|
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
|
|
|
|
|
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
|
|
|
|
|
|
|
|
|
|
// 设置最后修改时间
|
|
|
|
|
mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(this,
|
|
|
|
|
@ -529,7 +547,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
* is not ready
|
|
|
|
|
*/
|
|
|
|
|
showAlertHeader(); // 显示提醒头部
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 加载现有标签
|
|
|
|
|
loadExistingTags();
|
|
|
|
|
}
|
|
|
|
|
@ -765,7 +783,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
Log.e(TAG, "RichEditor is null! Check layout file.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化浮动富文本工具栏
|
|
|
|
|
mFloatingToolbar = findViewById(R.id.floating_editor_toolbar);
|
|
|
|
|
if (mFloatingToolbar != null) {
|
|
|
|
|
@ -838,6 +856,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
|
|
|
|
|
// 初始化富文本功能按钮
|
|
|
|
|
initRichEditorButtons();
|
|
|
|
|
|
|
|
|
|
// 初始化背景管理器
|
|
|
|
|
mBackgroundManager = new BackgroundManager(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -892,10 +913,18 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
View.VISIBLE);
|
|
|
|
|
} else if (sBgSelectorBtnsMap.containsKey(id)) {
|
|
|
|
|
// 处理背景颜色选择
|
|
|
|
|
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
|
|
|
|
|
View.GONE);
|
|
|
|
|
mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));
|
|
|
|
|
mNoteBgColorSelector.setVisibility(View.GONE);
|
|
|
|
|
Integer bgColorId = sBgSelectorBtnsMap.get(id);
|
|
|
|
|
if (bgColorId == -1) {
|
|
|
|
|
// 处理自定义背景图片选择
|
|
|
|
|
mNoteBgColorSelector.setVisibility(View.GONE);
|
|
|
|
|
pickBackgroundImageFromGallery();
|
|
|
|
|
} else {
|
|
|
|
|
// 处理普通背景颜色选择
|
|
|
|
|
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
|
|
|
|
|
View.GONE);
|
|
|
|
|
mWorkingNote.setBgColorId(bgColorId);
|
|
|
|
|
mNoteBgColorSelector.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
} else if (sFontSizeBtnsMap.containsKey(id)) {
|
|
|
|
|
// 处理字体大小选择
|
|
|
|
|
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.GONE);
|
|
|
|
|
@ -913,7 +942,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
mFontSizeSelector.setVisibility(View.GONE);
|
|
|
|
|
} else if (id == R.id.btn_insert_image) {
|
|
|
|
|
// 处理插入图片按钮点击事件 OMO
|
|
|
|
|
// 处理插入图片按钮点击事件
|
|
|
|
|
pickImageFromGallery();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -1048,7 +1077,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 切换标签管理界面的显示/隐藏
|
|
|
|
|
*/
|
|
|
|
|
@ -1458,10 +1487,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
*/
|
|
|
|
|
private boolean saveNote() {
|
|
|
|
|
getWorkingText(); // 获取当前工作文本
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 保存标签数据
|
|
|
|
|
saveTagsToNote();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
boolean saved = mWorkingNote.saveNote(); // 保存笔记到数据库
|
|
|
|
|
if (saved) {
|
|
|
|
|
/**
|
|
|
|
|
@ -1475,20 +1504,20 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
return saved;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 将标签保存到笔记对象中
|
|
|
|
|
*/
|
|
|
|
|
private void saveTagsToNote() {
|
|
|
|
|
// 清空现有标签
|
|
|
|
|
mWorkingNote.clearTags();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 添加所有标签
|
|
|
|
|
for (String tag : mTagsList) {
|
|
|
|
|
mWorkingNote.addTag(tag);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 保存搜索历史记录
|
|
|
|
|
* @param query 搜索关键词
|
|
|
|
|
@ -1497,13 +1526,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
if (TextUtils.isEmpty(query)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 获取SharedPreferences
|
|
|
|
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 获取现有的搜索历史
|
|
|
|
|
String historyString = sp.getString(PREFERENCE_SEARCH_HISTORY, "");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 将搜索历史拆分为列表
|
|
|
|
|
ArrayList<String> historyList = new ArrayList<>();
|
|
|
|
|
if (!TextUtils.isEmpty(historyString)) {
|
|
|
|
|
@ -1514,18 +1543,18 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果搜索关键词已存在,先移除
|
|
|
|
|
historyList.remove(query);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 将新的搜索关键词添加到列表开头
|
|
|
|
|
historyList.add(0, query);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 限制搜索历史记录数量
|
|
|
|
|
if (historyList.size() > MAX_SEARCH_HISTORY) {
|
|
|
|
|
historyList = new ArrayList<>(historyList.subList(0, MAX_SEARCH_HISTORY));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 将搜索历史列表转换为字符串,用逗号分隔
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
for (int i = 0; i < historyList.size(); i++) {
|
|
|
|
|
@ -1534,7 +1563,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
sb.append(historyList.get(i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 保存到SharedPreferences
|
|
|
|
|
sp.edit().putString(PREFERENCE_SEARCH_HISTORY, sb.toString()).apply();
|
|
|
|
|
}
|
|
|
|
|
@ -1627,13 +1656,44 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
// 意图:打开系统相册选择图片
|
|
|
|
|
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
|
|
|
|
intent.setType("image/*"); // 只显示图片类型
|
|
|
|
|
startActivityForResult(intent, PHOTO_REQUEST); // 启动相册,等待返回结果
|
|
|
|
|
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE); // 启动相册,等待返回结果
|
|
|
|
|
} catch (ActivityNotFoundException e) {
|
|
|
|
|
// 如果没有相册应用,尝试使用通用选择器
|
|
|
|
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
|
|
|
|
intent.setType("image/*");
|
|
|
|
|
try {
|
|
|
|
|
startActivityForResult(intent, PHOTO_REQUEST);
|
|
|
|
|
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
|
|
|
|
|
} catch (ActivityNotFoundException ex) {
|
|
|
|
|
showToast(R.string.error_permission_denied);
|
|
|
|
|
Log.e(TAG, "No image picker available", ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从相册选择背景图片
|
|
|
|
|
*/
|
|
|
|
|
private void pickBackgroundImageFromGallery() {
|
|
|
|
|
// 检查运行时权限
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
|
|
|
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
|
|
|
|
// 请求权限
|
|
|
|
|
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_PERMISSION_STORAGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 意图:打开系统相册选择图片
|
|
|
|
|
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
|
|
|
|
intent.setType("image/*"); // 只显示图片类型
|
|
|
|
|
startActivityForResult(intent, REQUEST_CODE_PICK_BACKGROUND); // 启动相册,等待返回结果
|
|
|
|
|
} catch (ActivityNotFoundException e) {
|
|
|
|
|
// 如果没有相册应用,尝试使用通用选择器
|
|
|
|
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
|
|
|
|
intent.setType("image/*");
|
|
|
|
|
try {
|
|
|
|
|
startActivityForResult(intent, REQUEST_CODE_PICK_BACKGROUND);
|
|
|
|
|
} catch (ActivityNotFoundException ex) {
|
|
|
|
|
showToast(R.string.error_permission_denied);
|
|
|
|
|
Log.e(TAG, "No image picker available", ex);
|
|
|
|
|
@ -1662,79 +1722,103 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
@Override
|
|
|
|
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
|
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
|
|
|
if (requestCode == PHOTO_REQUEST && resultCode == RESULT_OK && data != null) {
|
|
|
|
|
Uri uri = data.getData();
|
|
|
|
|
String imageBase64 = saveImageToBase64(uri);
|
|
|
|
|
if (imageBase64 == null) return; // 转换失败就退出
|
|
|
|
|
|
|
|
|
|
// 1. 拼接RichEditor支持的<img>标签,使用Base64编码的图片数据
|
|
|
|
|
String imgHtmlTag = "<img src=\"" + imageBase64 + "\" width=\"200\" height=\"200\"/><br/>";
|
|
|
|
|
|
|
|
|
|
// 2. 直接保存到笔记内容中(结合原有插入逻辑)
|
|
|
|
|
String originalContent = mWorkingNote.getContent() == null ? "" : mWorkingNote.getContent();
|
|
|
|
|
Log.d(TAG, "Original note content: " + originalContent);
|
|
|
|
|
|
|
|
|
|
// 3. 插入图片到RichEditor,兼容空内容情况
|
|
|
|
|
String curHtml = mNoteEditor.getHtml();
|
|
|
|
|
if (curHtml == null || curHtml.isEmpty()) {
|
|
|
|
|
// 对于空内容,直接使用图片标签
|
|
|
|
|
mNoteEditor.setHtml(imgHtmlTag);
|
|
|
|
|
} else {
|
|
|
|
|
// 对于已有内容,追加图片标签
|
|
|
|
|
String newHtml = curHtml + imgHtmlTag;
|
|
|
|
|
mNoteEditor.setHtml(newHtml);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. 同时更新工作笔记内容,确保新建笔记也能正确保存
|
|
|
|
|
String updatedHtml = mNoteEditor.getHtml();
|
|
|
|
|
mWorkingNote.setWorkingText(updatedHtml);
|
|
|
|
|
|
|
|
|
|
// 弹窗依然保留
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
|
|
|
builder.setTitle("图片选择成功!");
|
|
|
|
|
|
|
|
|
|
ImageView imageView = new ImageView(this);
|
|
|
|
|
imageView.setLayoutParams(new ViewGroup.LayoutParams(
|
|
|
|
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
|
|
|
ViewGroup.LayoutParams.WRAP_CONTENT)); // 加布局参数,避免图片显示不全
|
|
|
|
|
imageView.setImageURI(uri); // 弹窗显示原始图片
|
|
|
|
|
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); // 适配图片大小
|
|
|
|
|
builder.setView(imageView);
|
|
|
|
|
|
|
|
|
|
builder.setPositiveButton("确认", (dialog, which) -> {
|
|
|
|
|
// 保存HTML内容,包含Base64编码的图片
|
|
|
|
|
String currentHtml = mNoteEditor.getHtml();
|
|
|
|
|
Log.d("NoteDebug", "准备保存的HTML内容:" + currentHtml);
|
|
|
|
|
|
|
|
|
|
// 执行保存操作
|
|
|
|
|
mWorkingNote.setWorkingText(currentHtml);
|
|
|
|
|
boolean isSaved = mWorkingNote.saveNote();
|
|
|
|
|
|
|
|
|
|
// 根据保存结果提示(更友好)
|
|
|
|
|
if (isSaved) {
|
|
|
|
|
Toast.makeText(this, "图片信息已保存!", Toast.LENGTH_SHORT).show();
|
|
|
|
|
if (resultCode == RESULT_OK && data != null) {
|
|
|
|
|
if (requestCode == PHOTO_REQUEST || requestCode == REQUEST_CODE_PICK_IMAGE) {
|
|
|
|
|
Uri uri = data.getData();
|
|
|
|
|
String imageBase64 = saveImageToBase64(uri);
|
|
|
|
|
if (imageBase64 == null) return; // 转换失败就退出
|
|
|
|
|
|
|
|
|
|
// 1. 拼接RichEditor支持的<img>标签,使用Base64编码的图片数据
|
|
|
|
|
String imgHtmlTag = "<img src=\"" + imageBase64 + "\" width=\"200\" height=\"200\"/><br/>";
|
|
|
|
|
|
|
|
|
|
// 2. 直接保存到笔记内容中(结合原有插入逻辑)
|
|
|
|
|
String originalContent = mWorkingNote.getContent() == null ? "" : mWorkingNote.getContent();
|
|
|
|
|
Log.d(TAG, "Original note content: " + originalContent);
|
|
|
|
|
|
|
|
|
|
// 3. 插入图片到RichEditor,兼容空内容情况
|
|
|
|
|
String curHtml = mNoteEditor.getHtml();
|
|
|
|
|
if (curHtml == null || curHtml.isEmpty()) {
|
|
|
|
|
// 对于空内容,直接使用图片标签
|
|
|
|
|
mNoteEditor.setHtml(imgHtmlTag);
|
|
|
|
|
} else {
|
|
|
|
|
// 如果保存返回false,可能是因为内容未变化,而不是真正的失败
|
|
|
|
|
Toast.makeText(this, "图片信息已保存!", Toast.LENGTH_SHORT).show();
|
|
|
|
|
Log.d(TAG, "Note save returned false, but image was successfully inserted");
|
|
|
|
|
// 对于已有内容,追加图片标签
|
|
|
|
|
String newHtml = curHtml + imgHtmlTag;
|
|
|
|
|
mNoteEditor.setHtml(newHtml);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
builder.setNegativeButton("取消", (dialog, which) -> {
|
|
|
|
|
// 如果用户取消,移除刚才插入的图片
|
|
|
|
|
String currentHtml = mNoteEditor.getHtml();
|
|
|
|
|
if (currentHtml != null && currentHtml.endsWith(imgHtmlTag)) {
|
|
|
|
|
String cancelNewHtml = currentHtml.substring(0, currentHtml.length() - imgHtmlTag.length());
|
|
|
|
|
mNoteEditor.setHtml(cancelNewHtml);
|
|
|
|
|
// 同时更新工作笔记
|
|
|
|
|
mWorkingNote.setWorkingText(cancelNewHtml);
|
|
|
|
|
} else if (currentHtml != null && currentHtml.equals(imgHtmlTag)) {
|
|
|
|
|
// 如果只有这一张图片,取消后清空内容
|
|
|
|
|
mNoteEditor.setHtml("");
|
|
|
|
|
mWorkingNote.setWorkingText("");
|
|
|
|
|
// 4. 同时更新工作笔记内容,确保新建笔记也能正确保存
|
|
|
|
|
String updatedHtml = mNoteEditor.getHtml();
|
|
|
|
|
mWorkingNote.setWorkingText(updatedHtml);
|
|
|
|
|
|
|
|
|
|
// 弹窗依然保留
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
|
|
|
builder.setTitle("图片选择成功!");
|
|
|
|
|
|
|
|
|
|
ImageView imageView = new ImageView(this);
|
|
|
|
|
imageView.setLayoutParams(new ViewGroup.LayoutParams(
|
|
|
|
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
|
|
|
ViewGroup.LayoutParams.WRAP_CONTENT)); // 加布局参数,避免图片显示不全
|
|
|
|
|
imageView.setImageURI(uri); // 弹窗显示原始图片
|
|
|
|
|
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); // 适配图片大小
|
|
|
|
|
builder.setView(imageView);
|
|
|
|
|
|
|
|
|
|
builder.setPositiveButton("确认", (dialog, which) -> {
|
|
|
|
|
// 保存HTML内容,包含Base64编码的图片
|
|
|
|
|
String currentHtml = mNoteEditor.getHtml();
|
|
|
|
|
Log.d("NoteDebug", "准备保存的HTML内容:" + currentHtml);
|
|
|
|
|
|
|
|
|
|
// 执行保存操作
|
|
|
|
|
mWorkingNote.setWorkingText(currentHtml);
|
|
|
|
|
boolean isSaved = mWorkingNote.saveNote();
|
|
|
|
|
|
|
|
|
|
// 根据保存结果提示(更友好)
|
|
|
|
|
if (isSaved) {
|
|
|
|
|
Toast.makeText(this, "图片信息已保存!", Toast.LENGTH_SHORT).show();
|
|
|
|
|
} else {
|
|
|
|
|
// 如果保存返回false,可能是因为内容未变化,而不是真正的失败
|
|
|
|
|
Toast.makeText(this, "图片信息已保存!", Toast.LENGTH_SHORT).show();
|
|
|
|
|
Log.d(TAG, "Note save returned false, but image was successfully inserted");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
builder.setNegativeButton("取消", (dialog, which) -> {
|
|
|
|
|
// 如果用户取消,移除刚才插入的图片
|
|
|
|
|
String currentHtml = mNoteEditor.getHtml();
|
|
|
|
|
if (currentHtml != null && currentHtml.endsWith(imgHtmlTag)) {
|
|
|
|
|
String cancelNewHtml = currentHtml.substring(0, currentHtml.length() - imgHtmlTag.length());
|
|
|
|
|
mNoteEditor.setHtml(cancelNewHtml);
|
|
|
|
|
// 同时更新工作笔记
|
|
|
|
|
mWorkingNote.setWorkingText(cancelNewHtml);
|
|
|
|
|
} else if (currentHtml != null && currentHtml.equals(imgHtmlTag)) {
|
|
|
|
|
// 如果只有这一张图片,取消后清空内容
|
|
|
|
|
mNoteEditor.setHtml("");
|
|
|
|
|
mWorkingNote.setWorkingText("");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
builder.show();
|
|
|
|
|
}
|
|
|
|
|
else if (requestCode == REQUEST_CODE_PICK_BACKGROUND) {
|
|
|
|
|
// 处理背景图片选择的情况
|
|
|
|
|
Uri uri = data.getData();
|
|
|
|
|
String backgroundPath = mBackgroundManager.saveBackgroundImage(uri);
|
|
|
|
|
if (backgroundPath != null) {
|
|
|
|
|
// 设置自定义背景路径
|
|
|
|
|
mWorkingNote.setCustomBackgroundPath(backgroundPath);
|
|
|
|
|
// 应用背景图片
|
|
|
|
|
Drawable background = mBackgroundManager.loadBackground(backgroundPath);
|
|
|
|
|
if (background != null) {
|
|
|
|
|
mNoteEditorPanel.setBackground(background);
|
|
|
|
|
mHeadViewPanel.setBackground(background);
|
|
|
|
|
}
|
|
|
|
|
// 隐藏背景选择器
|
|
|
|
|
mNoteBgColorSelector.setVisibility(View.GONE);
|
|
|
|
|
// 显示保存成功提示
|
|
|
|
|
Toast.makeText(this, "背景图片设置成功!", Toast.LENGTH_SHORT).show();
|
|
|
|
|
} else {
|
|
|
|
|
// 显示保存失败提示
|
|
|
|
|
Toast.makeText(this, "背景图片设置失败!", Toast.LENGTH_SHORT).show();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
builder.show();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1807,7 +1891,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
mNoteEditor.setEditorFontSize(18); // 默认值
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 初始化标签管理相关控件和事件监听器
|
|
|
|
|
*/
|
|
|
|
|
@ -1817,10 +1901,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
mExistingTagsContainer = findViewById(R.id.existing_tags_container);
|
|
|
|
|
mTagInput = findViewById(R.id.et_tag_input);
|
|
|
|
|
mAddTagButton = findViewById(R.id.btn_add_tag);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化标签列表
|
|
|
|
|
mTagsList = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置添加标签按钮的点击事件
|
|
|
|
|
mAddTagButton.setOnClickListener(new OnClickListener() {
|
|
|
|
|
@Override
|
|
|
|
|
@ -1828,30 +1912,30 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
addTag();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 加载现有标签
|
|
|
|
|
loadExistingTags();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 添加标签
|
|
|
|
|
*/
|
|
|
|
|
private void addTag() {
|
|
|
|
|
String tagName = mTagInput.getText().toString().trim();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查标签是否有效
|
|
|
|
|
if (isValidTag(tagName)) {
|
|
|
|
|
// 添加标签到列表
|
|
|
|
|
mTagsList.add(tagName);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新UI显示
|
|
|
|
|
updateTagsDisplay();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 清空输入框
|
|
|
|
|
mTagInput.setText("");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检查标签是否有效
|
|
|
|
|
* @param tagName 标签名称
|
|
|
|
|
@ -1863,41 +1947,41 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
Toast.makeText(this, "标签不能为空", Toast.LENGTH_SHORT).show();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查标签长度
|
|
|
|
|
if (tagName.length() < 1 || tagName.length() > 15) {
|
|
|
|
|
Toast.makeText(this, "标签长度必须在1-15个字符之间", Toast.LENGTH_SHORT).show();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查标签数量是否超过限制
|
|
|
|
|
if (mTagsList.size() >= 5) {
|
|
|
|
|
Toast.makeText(this, "每个笔记最多只能添加5个标签", Toast.LENGTH_SHORT).show();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查标签是否已存在
|
|
|
|
|
if (mTagsList.contains(tagName)) {
|
|
|
|
|
Toast.makeText(this, "该标签已存在", Toast.LENGTH_SHORT).show();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 更新标签显示
|
|
|
|
|
*/
|
|
|
|
|
private void updateTagsDisplay() {
|
|
|
|
|
// 清空现有标签容器
|
|
|
|
|
mExistingTagsContainer.removeAllViews();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 添加所有标签到容器
|
|
|
|
|
for (final String tag : mTagsList) {
|
|
|
|
|
// 创建标签管理区域的标签视图
|
|
|
|
|
LinearLayout tagView = new LinearLayout(this);
|
|
|
|
|
LinearLayout.LayoutParams tagViewParams = new LinearLayout.LayoutParams(
|
|
|
|
|
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
|
|
|
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
|
|
|
36);
|
|
|
|
|
tagViewParams.setMargins(0, 0, 8, 0);
|
|
|
|
|
tagView.setLayoutParams(tagViewParams);
|
|
|
|
|
@ -1907,7 +1991,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
tagView.setBackgroundResource(R.drawable.bg_color_btn_mask);
|
|
|
|
|
tagView.setClickable(true);
|
|
|
|
|
tagView.setFocusable(true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建标签文本
|
|
|
|
|
TextView tagText = new TextView(this);
|
|
|
|
|
tagText.setText(tag);
|
|
|
|
|
@ -1916,7 +2000,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
tagText.setPadding(0, 0, 8, 0);
|
|
|
|
|
tagText.setSingleLine(true);
|
|
|
|
|
tagText.setTextSize(14);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建删除按钮
|
|
|
|
|
ImageView deleteButton = new ImageView(this);
|
|
|
|
|
LinearLayout.LayoutParams deleteParams = new LinearLayout.LayoutParams(
|
|
|
|
|
@ -1927,7 +2011,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
deleteButton.setClickable(true);
|
|
|
|
|
deleteButton.setFocusable(true);
|
|
|
|
|
deleteButton.setTag(tag);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置删除按钮点击事件
|
|
|
|
|
deleteButton.setOnClickListener(new OnClickListener() {
|
|
|
|
|
@Override
|
|
|
|
|
@ -1936,16 +2020,16 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
removeTag(tagToRemove);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 添加控件到标签视图
|
|
|
|
|
tagView.addView(tagText);
|
|
|
|
|
tagView.addView(deleteButton);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 添加标签视图到容器
|
|
|
|
|
mExistingTagsContainer.addView(tagView);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 移除标签
|
|
|
|
|
* @param tagName 要移除的标签名称
|
|
|
|
|
@ -1954,7 +2038,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
mTagsList.remove(tagName);
|
|
|
|
|
updateTagsDisplay();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 设置浮动富文本工具栏的拖拽功能
|
|
|
|
|
*/
|
|
|
|
|
@ -1963,14 +2047,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
final boolean[] isDragging = {false};
|
|
|
|
|
final int[] lastX = {0};
|
|
|
|
|
final int[] lastY = {0};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置触摸监听器
|
|
|
|
|
mFloatingToolbar.setOnTouchListener(new OnTouchListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onTouch(View v, MotionEvent event) {
|
|
|
|
|
int x = (int) event.getRawX();
|
|
|
|
|
int y = (int) event.getRawY();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (event.getAction()) {
|
|
|
|
|
case MotionEvent.ACTION_DOWN:
|
|
|
|
|
// 记录初始触摸位置
|
|
|
|
|
@ -1982,44 +2066,44 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
// 计算移动距离
|
|
|
|
|
int deltaX = x - lastX[0];
|
|
|
|
|
int deltaY = y - lastY[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 判断是否开始拖拽
|
|
|
|
|
if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) {
|
|
|
|
|
isDragging[0] = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isDragging[0]) {
|
|
|
|
|
// 更新工具栏位置
|
|
|
|
|
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算新的位置
|
|
|
|
|
int newLeftMargin = params.leftMargin + deltaX;
|
|
|
|
|
int newTopMargin = params.topMargin + deltaY;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 限制位置在屏幕范围内
|
|
|
|
|
DisplayMetrics displayMetrics = new DisplayMetrics();
|
|
|
|
|
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
|
|
|
|
int screenWidth = displayMetrics.widthPixels;
|
|
|
|
|
int screenHeight = displayMetrics.heightPixels;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算工具栏宽度和高度
|
|
|
|
|
int toolbarWidth = v.getWidth();
|
|
|
|
|
int toolbarHeight = v.getHeight();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 限制左边界
|
|
|
|
|
newLeftMargin = Math.max(0, Math.min(newLeftMargin, screenWidth - toolbarWidth));
|
|
|
|
|
// 限制上边界
|
|
|
|
|
newTopMargin = Math.max(0, Math.min(newTopMargin, screenHeight - toolbarHeight));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新布局参数
|
|
|
|
|
params.leftMargin = newLeftMargin;
|
|
|
|
|
params.topMargin = newTopMargin;
|
|
|
|
|
v.setLayoutParams(params);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新最后触摸位置
|
|
|
|
|
lastX[0] = x;
|
|
|
|
|
lastY[0] = y;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; // 消耗事件
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
@ -2031,12 +2115,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return false; // 不消耗事件,允许其他触摸事件处理
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 加载现有标签
|
|
|
|
|
*/
|
|
|
|
|
@ -2049,7 +2133,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
Notes.DataColumns.NOTE_ID + "=? AND " + Notes.DataColumns.MIME_TYPE + "=?",
|
|
|
|
|
new String[]{String.valueOf(mWorkingNote.getNoteId()), Notes.DataConstants.TAG},
|
|
|
|
|
null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (cursor != null) {
|
|
|
|
|
while (cursor.moveToNext()) {
|
|
|
|
|
String tagName = cursor.getString(0);
|
|
|
|
|
@ -2059,12 +2143,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
}
|
|
|
|
|
cursor.close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新UI显示
|
|
|
|
|
updateTagsDisplay();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化富文本编辑器配置
|
|
|
|
|
private void initRichEditor() {
|
|
|
|
|
mNoteEditor.setEditorHeight(600); // 设置编辑器高度
|
|
|
|
|
@ -2073,6 +2157,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|
|
|
|
|
mNoteEditor.setPadding(10, 10, 10, 10); // 内边距
|
|
|
|
|
mNoteEditor.setPlaceholder("请输入笔记内容..."); // 占位提示
|
|
|
|
|
mNoteEditor.setInputEnabled(true); // 允许输入
|
|
|
|
|
mNoteEditor.setEditorBackgroundColor(0x00000000); // 设置背景透明
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加富文本功能按钮初始化方法
|
|
|
|
|
|