diff --git a/java/net/micode/notes/ui/NoteEditText.java b/java/net/micode/notes/ui/NoteEditText.java index 2afe2a8..8eaa2c1 100644 --- a/java/net/micode/notes/ui/NoteEditText.java +++ b/java/net/micode/notes/ui/NoteEditText.java @@ -1,17 +1,6 @@ /* - * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 版权声明: MiCode 开源社区 版权所有 + * 本文件遵循 Apache License, Version 2.0 许可协议 */ package net.micode.notes.ui; @@ -37,15 +26,17 @@ import net.micode.notes.R; import java.util.HashMap; import java.util.Map; +// 定义 NoteEditText 类,继承自 EditText,用于笔记编辑文本框 public class NoteEditText extends EditText { - private static final String TAG = "NoteEditText"; - private int mIndex; - private int mSelectionStartBeforeDelete; + private static final String TAG = "NoteEditText"; // 日志标签 + private int mIndex; // 当前编辑文本的索引 + private int mSelectionStartBeforeDelete; // 删除前的光标起始位置 - private static final String SCHEME_TEL = "tel:" ; - private static final String SCHEME_HTTP = "http:" ; - private static final String SCHEME_EMAIL = "mailto:" ; + private static final String SCHEME_TEL = "tel:"; // 电话 URI scheme + private static final String SCHEME_HTTP = "http:"; // HTTP URI scheme + private static final String SCHEME_EMAIL = "mailto:"; // 邮件 URI scheme + // 定义 URI scheme 和对应操作资源 ID 的映射关系 private static final Map sSchemaActionResMap = new HashMap(); static { sSchemaActionResMap.put(SCHEME_TEL, R.string.note_link_tel); @@ -54,56 +45,59 @@ public class NoteEditText extends EditText { } /** - * Call by the {@link NoteEditActivity} to delete or add edit text + * 由 NoteEditActivity 调用,用于删除或添加编辑文本 */ public interface OnTextViewChangeListener { /** - * Delete current edit text when {@link KeyEvent#KEYCODE_DEL} happens - * and the text is null + * 当按下删除键且文本为空时,删除当前编辑文本 */ void onEditTextDelete(int index, String text); /** - * Add edit text after current edit text when {@link KeyEvent#KEYCODE_ENTER} - * happen + * 当按下回车键时,添加新的编辑文本 */ void onEditTextEnter(int index, String text); /** - * Hide or show item option when text change + * 当文本变化时,隐藏或显示选项菜单项 */ void onTextChange(int index, boolean hasText); } - private OnTextViewChangeListener mOnTextViewChangeListener; + private OnTextViewChangeListener mOnTextViewChangeListener; // 编辑文本变化监听器 + // 构造函数 public NoteEditText(Context context) { super(context, null); - mIndex = 0; + mIndex = 0; // 默认索引为 0 } + // 设置编辑文本的索引 public void setIndex(int index) { mIndex = index; } + // 设置编辑文本变化监听器 public void setOnTextViewChangeListener(OnTextViewChangeListener listener) { mOnTextViewChangeListener = listener; } + // 构造函数 public NoteEditText(Context context, AttributeSet attrs) { super(context, attrs, android.R.attr.editTextStyle); } + // 构造函数 public NoteEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - // TODO Auto-generated constructor stub } + // 处理触摸事件,用于设置文本选择 @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: - + // 计算触摸位置相对于文本的偏移量 int x = (int) event.getX(); int y = (int) event.getY(); x -= getTotalPaddingLeft(); @@ -112,75 +106,84 @@ public class NoteEditText extends EditText { y += getScrollY(); Layout layout = getLayout(); - int line = layout.getLineForVertical(y); - int off = layout.getOffsetForHorizontal(line, x); - Selection.setSelection(getText(), off); + int line = layout.getLineForVertical(y); // 获取垂直位置对应的行号 + int off = layout.getOffsetForHorizontal(line, x); // 获取水平位置对应的偏移量 + Selection.setSelection(getText(), off); // 设置文本选择 break; } - return super.onTouchEvent(event); + return super.onTouchEvent(event); // 调用父类的触摸事件处理方法 } + // 处理键盘按下事件 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_ENTER: + // 如果设置了编辑文本变化监听器,则不允许处理回车键事件 if (mOnTextViewChangeListener != null) { return false; } break; case KeyEvent.KEYCODE_DEL: - mSelectionStartBeforeDelete = getSelectionStart(); + mSelectionStartBeforeDelete = getSelectionStart(); // 保存删除前的光标起始位置 break; default: break; } - return super.onKeyDown(keyCode, event); + return super.onKeyDown(keyCode, event); // 调用父类的键盘按下事件处理方法 } + // 处理键盘弹起事件 @Override public boolean onKeyUp(int keyCode, KeyEvent event) { - switch(keyCode) { + switch (keyCode) { case KeyEvent.KEYCODE_DEL: + // 如果设置了编辑文本变化监听器,则处理删除事件 if (mOnTextViewChangeListener != null) { - if (0 == mSelectionStartBeforeDelete && mIndex != 0) { - mOnTextViewChangeListener.onEditTextDelete(mIndex, getText().toString()); + if (0 == mSelectionStartBeforeDelete && mIndex != 0) { // 如果光标在起始位置且不是第一个编辑文本 + mOnTextViewChangeListener.onEditTextDelete(mIndex, getText().toString()); // 删除当前编辑文本 return true; } } else { - Log.d(TAG, "OnTextViewChangeListener was not seted"); + Log.d(TAG, "未设置编辑文本变化监听器"); } break; case KeyEvent.KEYCODE_ENTER: + // 如果设置了编辑文本变化监听器,则处理回车键事件 if (mOnTextViewChangeListener != null) { - int selectionStart = getSelectionStart(); - String text = getText().subSequence(selectionStart, length()).toString(); - setText(getText().subSequence(0, selectionStart)); - mOnTextViewChangeListener.onEditTextEnter(mIndex + 1, text); + int selectionStart = getSelectionStart(); // 获取光标起始位置 + String text = getText().subSequence(selectionStart, length()).toString(); // 获取当前选择的文本 + setText(getText().subSequence(0, selectionStart)); // 设置文本为选择位置之前的内容 + mOnTextViewChangeListener.onEditTextEnter(mIndex + 1, text); // 添加新的编辑文本 } else { - Log.d(TAG, "OnTextViewChangeListener was not seted"); + Log.d(TAG, "未设置编辑文本变化监听器"); } break; default: break; } - return super.onKeyUp(keyCode, event); + return super.onKeyUp(keyCode, event); // 调用父类的键盘弹起事件处理方法 } + // 处理焦点变化事件 @Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { + // 如果设置了编辑文本变化监听器,则通知文本变化 if (mOnTextViewChangeListener != null) { - if (!focused && TextUtils.isEmpty(getText())) { - mOnTextViewChangeListener.onTextChange(mIndex, false); + if (!focused && TextUtils.isEmpty(getText())) { // 如果失去焦点且文本为空 + mOnTextViewChangeListener.onTextChange(mIndex, false); // 通知文本为空 } else { - mOnTextViewChangeListener.onTextChange(mIndex, true); + mOnTextViewChangeListener.onTextChange(mIndex, true); // 通知文本不为空 } } - super.onFocusChanged(focused, direction, previouslyFocusedRect); + super.onFocusChanged(focused, direction, previouslyFocusedRect); // 调用父类的焦点变化事件处理方法 } + // 创建上下文菜单 @Override protected void onCreateContextMenu(ContextMenu menu) { + // 如果文本是 Spanned 类型,则处理 URLSpan if (getText() instanceof Spanned) { int selStart = getSelectionStart(); int selEnd = getSelectionEnd(); @@ -188,30 +191,31 @@ public class NoteEditText extends EditText { int min = Math.min(selStart, selEnd); int max = Math.max(selStart, selEnd); - final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class); - if (urls.length == 1) { + final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class); // 获取选中文本中的 URLSpan + if (urls.length == 1) { // 如果只有一个 URLSpan int defaultResId = 0; - for(String schema: sSchemaActionResMap.keySet()) { - if(urls[0].getURL().indexOf(schema) >= 0) { + // 遍历 URI scheme 和操作资源 ID 的映射关系,找到对应的资源 ID + for (String schema : sSchemaActionResMap.keySet()) { + if (urls[0].getURL().indexOf(schema) >= 0) { defaultResId = sSchemaActionResMap.get(schema); break; } } - if (defaultResId == 0) { + if (defaultResId == 0) { // 如果未找到对应的资源 ID,则使用默认资源 ID defaultResId = R.string.note_link_other; } + // 添加菜单项并设置点击监听器 menu.add(0, 0, 0, defaultResId).setOnMenuItemClickListener( new OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { - // goto a new intent - urls[0].onClick(NoteEditText.this); + urls[0].onClick(NoteEditText.this); // 跳转到对应链接 return true; } }); } } - super.onCreateContextMenu(menu); + super.onCreateContextMenu(menu); // 调用父类的上下文菜单创建方法 } -} +} \ No newline at end of file