customTemplates = new ArrayList<>();
+ for (NoteTemplate template : mTemplates) {
+ if (NoteTemplate.TYPE_CUSTOM.equals(template.getType())) {
+ customTemplates.add(template);
+ }
+ }
+ return customTemplates;
+ }
+
+ /**
+ * 根据ID获取模板
+ */
+ public NoteTemplate getTemplateById(long id) {
+ for (NoteTemplate template : mTemplates) {
+ if (template.getId() == id) {
+ return template;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 添加自定义模板
+ */
+ public void addCustomTemplate(NoteTemplate template) {
+ // 生成唯一ID
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
+ long id = prefs.getLong(PREF_TEMPLATE_ID_COUNTER, 1000);
+
+ template.setId(id);
+ template.setType(NoteTemplate.TYPE_CUSTOM);
+ template.setCreateTime(System.currentTimeMillis());
+ template.setUpdateTime(System.currentTimeMillis());
+
+ mTemplates.add(template);
+
+ // 更新ID计数器
+ prefs.edit().putLong(PREF_TEMPLATE_ID_COUNTER, id + 1).apply();
+
+ // 保存自定义模板
+ saveCustomTemplates();
+ }
+
+ /**
+ * 删除自定义模板
+ */
+ public boolean deleteCustomTemplate(long id) {
+ NoteTemplate templateToRemove = null;
+ for (NoteTemplate template : mTemplates) {
+ if (template.getId() == id && NoteTemplate.TYPE_CUSTOM.equals(template.getType())) {
+ templateToRemove = template;
+ break;
+ }
+ }
+
+ if (templateToRemove != null) {
+ mTemplates.remove(templateToRemove);
+ saveCustomTemplates();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 更新自定义模板
+ */
+ public boolean updateCustomTemplate(NoteTemplate updatedTemplate) {
+ for (int i = 0; i < mTemplates.size(); i++) {
+ NoteTemplate template = mTemplates.get(i);
+ if (template.getId() == updatedTemplate.getId() &&
+ NoteTemplate.TYPE_CUSTOM.equals(template.getType())) {
+
+ updatedTemplate.setUpdateTime(System.currentTimeMillis());
+ mTemplates.set(i, updatedTemplate);
+ saveCustomTemplates();
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/net/micode/notes/ui/NoteEditActivity.java b/src/main/java/net/micode/notes/ui/NoteEditActivity.java
index 184fe3b..2777247 100644
--- a/src/main/java/net/micode/notes/ui/NoteEditActivity.java
+++ b/src/main/java/net/micode/notes/ui/NoteEditActivity.java
@@ -141,6 +141,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/** 日志标签 */
private static final String TAG = "NoteEditActivity";
+ /** 请求选择模板的请求码 */
+ private static final int REQUEST_SELECT_TEMPLATE = 100;
/** 头部视图持有者 */
private HeadViewHolder mNoteHeaderHolder;
@@ -764,12 +766,43 @@ public class NoteEditActivity extends Activity implements OnClickListener,
case R.id.menu_unlock:
showPasswordDialogForUnlock();
break;
+ case R.id.menu_template:
+ // 启动模板选择Activity
+ Intent intent = new Intent(this, TemplateSelectActivity.class);
+ getWorkingText();
+ intent.putExtra(TemplateSelectActivity.EXTRA_CURRENT_NOTE_CONTENT, mWorkingNote.getContent());
+ startActivityForResult(intent, REQUEST_SELECT_TEMPLATE);
+ break;
default:
break;
}
return true;
}
+ /**
+ * 处理从其他Activity返回的结果
+ */
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == REQUEST_SELECT_TEMPLATE && resultCode == RESULT_OK && data != null) {
+ // 获取选择的模板内容
+ String templateContent = data.getStringExtra(TemplateSelectActivity.EXTRA_TEMPLATE_CONTENT);
+ if (templateContent != null) {
+ // 应用模板内容到当前笔记
+ mWorkingNote.setWorkingText(templateContent);
+ if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
+ switchToListMode(templateContent);
+ } else {
+ // 解析HTML格式的富文本内容,确保粗体和回车能正确显示
+ CharSequence htmlContent = Html.fromHtml(templateContent);
+ mNoteEditor.setText(getHighlightQueryResult(htmlContent, mUserQuery));
+ mNoteEditor.setSelection(mNoteEditor.getText().length());
+ }
+ }
+ }
+ }
+
/**
* 设置笔记的提醒时间
*
diff --git a/src/main/java/net/micode/notes/ui/TemplateSelectActivity.java b/src/main/java/net/micode/notes/ui/TemplateSelectActivity.java
new file mode 100644
index 0000000..46999d5
--- /dev/null
+++ b/src/main/java/net/micode/notes/ui/TemplateSelectActivity.java
@@ -0,0 +1,207 @@
+package net.micode.notes.ui;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import net.micode.notes.R;
+import net.micode.notes.model.NoteTemplate;
+import net.micode.notes.model.TemplateManager;
+
+import java.util.List;
+
+/**
+ * 模板选择Activity,用于展示和选择笔记模板
+ */
+public class TemplateSelectActivity extends Activity {
+ public static final String EXTRA_TEMPLATE_CONTENT = "template_content";
+ public static final String EXTRA_CURRENT_NOTE_CONTENT = "current_note_content";
+
+ private RecyclerView mRecyclerView;
+ private TemplateAdapter mAdapter;
+ private List mTemplates;
+ private TemplateManager mTemplateManager;
+ private String mCurrentNoteContent;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.template_select);
+
+ // 获取当前笔记内容
+ mCurrentNoteContent = getIntent().getStringExtra(EXTRA_CURRENT_NOTE_CONTENT);
+
+ // 初始化模板管理器
+ mTemplateManager = TemplateManager.getInstance(this);
+ mTemplates = mTemplateManager.getAllTemplates();
+
+ // 初始化RecyclerView
+ mRecyclerView = findViewById(R.id.rv_templates);
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+ mAdapter = new TemplateAdapter(mTemplates);
+ mRecyclerView.setAdapter(mAdapter);
+
+ // 初始化按钮点击事件
+ findViewById(R.id.btn_close).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ });
+
+ findViewById(R.id.btn_save_as_template).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ saveAsTemplate();
+ }
+ });
+ }
+
+ /**
+ * 保存当前笔记作为自定义模板
+ */
+ private void saveAsTemplate() {
+ if (TextUtils.isEmpty(mCurrentNoteContent)) {
+ Toast.makeText(this, R.string.error_note_empty, Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ // 弹出对话框输入模板名称
+ final EditText editText = new EditText(this);
+ editText.setHint(R.string.enter_template_name);
+
+ new AlertDialog.Builder(this)
+ .setTitle(R.string.save_as_template)
+ .setView(editText)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String templateName = editText.getText().toString().trim();
+ if (TextUtils.isEmpty(templateName)) {
+ Toast.makeText(TemplateSelectActivity.this, R.string.error_template_name_empty, Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ // 创建并保存自定义模板
+ NoteTemplate template = new NoteTemplate();
+ template.setName(templateName);
+ template.setContent(mCurrentNoteContent);
+ template.setType(NoteTemplate.TYPE_CUSTOM);
+
+ mTemplateManager.addCustomTemplate(template);
+
+ // 更新模板列表
+ mTemplates = mTemplateManager.getAllTemplates();
+ mAdapter = new TemplateAdapter(mTemplates);
+ mRecyclerView.setAdapter(mAdapter);
+
+ Toast.makeText(TemplateSelectActivity.this, R.string.message_template_saved, Toast.LENGTH_SHORT).show();
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, null)
+ .show();
+ }
+
+ /**
+ * 模板适配器,用于在RecyclerView中展示模板列表
+ */
+ private class TemplateAdapter extends RecyclerView.Adapter {
+ private List mTemplates;
+
+ public TemplateAdapter(List templates) {
+ mTemplates = templates;
+ }
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.template_item, parent, false);
+ return new ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ final NoteTemplate template = mTemplates.get(position);
+
+ holder.tvTemplateName.setText(template.getName());
+
+ // 设置模板类型标识
+ if (NoteTemplate.TYPE_SYSTEM.equals(template.getType())) {
+ holder.tvTemplateType.setText(R.string.template_type_system);
+ holder.ivDelete.setVisibility(View.GONE);
+ } else {
+ holder.tvTemplateType.setText(R.string.template_type_custom);
+ holder.ivDelete.setVisibility(View.VISIBLE);
+ }
+
+ // 设置点击事件
+ holder.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // 返回选择的模板内容
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_TEMPLATE_CONTENT, template.getContent());
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+ });
+
+ // 设置删除按钮点击事件
+ holder.ivDelete.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ new AlertDialog.Builder(TemplateSelectActivity.this)
+ .setTitle(R.string.alert_title_delete)
+ .setMessage(R.string.alert_message_delete_template)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // 删除自定义模板
+ mTemplateManager.deleteCustomTemplate(template.getId());
+
+ // 更新模板列表
+ mTemplates.clear();
+ mTemplates.addAll(mTemplateManager.getAllTemplates());
+ notifyDataSetChanged();
+
+ Toast.makeText(TemplateSelectActivity.this, R.string.message_template_deleted, Toast.LENGTH_SHORT).show();
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, null)
+ .show();
+ }
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return mTemplates.size();
+ }
+
+ public class ViewHolder extends RecyclerView.ViewHolder {
+ public TextView tvTemplateName;
+ public TextView tvTemplateType;
+ public ImageView ivDelete;
+
+ public ViewHolder(View itemView) {
+ super(itemView);
+ tvTemplateName = itemView.findViewById(R.id.tv_template_name);
+ tvTemplateType = itemView.findViewById(R.id.tv_template_type);
+ ivDelete = itemView.findViewById(R.id.iv_delete);
+ }
+ }
+ }
+}
diff --git a/src/main/res/drawable/template_item_bg.xml b/src/main/res/drawable/template_item_bg.xml
new file mode 100644
index 0000000..15117c7
--- /dev/null
+++ b/src/main/res/drawable/template_item_bg.xml
@@ -0,0 +1,21 @@
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
diff --git a/src/main/res/drawable/template_type_bg.xml b/src/main/res/drawable/template_type_bg.xml
new file mode 100644
index 0000000..94af0a3
--- /dev/null
+++ b/src/main/res/drawable/template_type_bg.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/src/main/res/layout/template_item.xml b/src/main/res/layout/template_item.xml
new file mode 100644
index 0000000..0834bb4
--- /dev/null
+++ b/src/main/res/layout/template_item.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/res/layout/template_select.xml b/src/main/res/layout/template_select.xml
new file mode 100644
index 0000000..e444f96
--- /dev/null
+++ b/src/main/res/layout/template_select.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/res/menu/note_edit.xml b/src/main/res/menu/note_edit.xml
index caee172..2f4f66b 100644
--- a/src/main/res/menu/note_edit.xml
+++ b/src/main/res/menu/note_edit.xml
@@ -57,4 +57,8 @@
+
+
\ No newline at end of file
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index ed89ef7..c959907 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -52,11 +52,21 @@
Unpin
Lock
Unlock
+ Note Template
+ Save as Template
+ System Template
+ Custom Template
Enter Password
Please enter password
Incorrect password
Note locked successfully
Note unlocked successfully
+ Enter Template Name
+ Note is empty
+ Template name cannot be empty
+ Template saved successfully
+ Template deleted successfully
+ Are you sure you want to delete this template?
%d selected
Nothing selected, the operation is invalid
Select all