You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
GPL_Project/other/06_210340061林亭旭_代码标注/NoteEditText.java

265 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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.
*/
package net.micode.notes.ui;
import android.content.Context;//抽象类提供了一组通用的API,通过 Context才能识别调用者
import android.graphics.Rect;
import android.text.Layout;
import android.text.Selection;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.URLSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.MotionEvent;
import android.widget.EditText;
import net.micode.notes.R;
import java.util.HashMap;
import java.util.Map;
public class NoteEditText extends EditText {//NoteEditText继承EditText的部分属性设置便签与文本框
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 Map<String, Integer> sSchemaActionResMap = new HashMap<String, Integer>();
//建立由字符和整数的hash表链接电话数据、网站数据与邮箱数据
static {
sSchemaActionResMap.put(SCHEME_TEL, R.string.note_link_tel);
sSchemaActionResMap.put(SCHEME_HTTP, R.string.note_link_web);
sSchemaActionResMap.put(SCHEME_EMAIL, R.string.note_link_email);
}
/**
* 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
*/
//当{@link KeyEvent#KEYCODE_DEL发生并且文本为空时删除当前编辑文本
void onEditTextDelete(int index, String text);
/**
* Add edit text after current edit text when {@link KeyEvent#KEYCODE_ENTER}
* happen
*/
//当{@link KeyEvent#KEYCODE_ENTER发生时在当前编辑文本后添加编辑文本
void onEditTextEnter(int index, String text);
/**
* Hide or show item option when text change
*/
//文本更改时隐藏或显示项目选项
void onTextChange(int index, boolean hasText);
}
private OnTextViewChangeListener mOnTextViewChangeListener;
public NoteEditText(Context context) {
super(context, null);//用super引用父类变量
mIndex = 0;
}//根据context设置文本
public void setIndex(int index) {
mIndex = index;
}//设置光标,并对光标进行初始化
public void setOnTextViewChangeListener(OnTextViewChangeListener listener) {
mOnTextViewChangeListener = listener;
}//令listener赋值给mOnTextViewChangeListener实现文本修改标记初始化
public NoteEditText(Context context, AttributeSet attrs) {
super(context, attrs, android.R.attr.editTextStyle);
}//规定context控件属性便于维护便签动态变化的属性
public NoteEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}//通过类型定义和引用父类变量实现defStyle的自动初始化
@Override
//view里的函数处理手机屏幕的所有事件
/*参数event为手机屏幕触摸事件封装类的对象其中封装了该事件的所有信息
例如触摸的位置、触摸的类型以及触摸的时间等。该对象会在用户触摸手机屏幕时被创建。*/
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
//对每一次屏幕被按下的情况进行重述
case MotionEvent.ACTION_DOWN:
//更新触屏坐标值
int x = (int) event.getX();
int y = (int) event.getY();
x -= getTotalPaddingLeft();
y -= getTotalPaddingTop();
x += getScrollX();
y += getScrollY();
Layout layout = getLayout();
//运用布局控件Layout对每一次的坐标新值xy进行设置新位置
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
Selection.setSelection(getText(), off);
//同过selection寻找并更新当前光标新坐标值
break;
}
return super.onTouchEvent(event);
//回溯至函数,实现对每一次触屏事件的计算
}
@Override
// 函数功能:处理用户按下一个键盘按键时会触发 的事件
public boolean onKeyDown(int keyCode, KeyEvent event) //当作为一个构造函数(带有运算符 new调用时Boolean() 将把它的参数转换成一个布尔值,并且返回一个包含该值的 Boolean 对象
{
switch (keyCode) {//根据按键的unicode编码值判断
case KeyEvent.KEYCODE_ENTER://按键编码值传入系统
if (mOnTextViewChangeListener != null)//对输入命令进行判空
{
return false;//对非法输入进行错误提示
}
break;
case KeyEvent.KEYCODE_DEL://删除按键
mSelectionStartBeforeDelete = getSelectionStart();
break;
default:
break;
}
return super.onKeyDown(keyCode, event);//继续进行父类其他点击事件
}
@Override
// 函数功能:处理用户松开一个键盘按键时会触发 的事件
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch(keyCode) {
//根据按键Unicode编码值进行操作包括进入和删除两种操作
case KeyEvent.KEYCODE_DEL:
if (mOnTextViewChangeListener != null) //判断是否被修改
{
if (0 == mSelectionStartBeforeDelete && mIndex != 0)//判断是否有被编辑修改并且文档不为空
{
mOnTextViewChangeListener.onEditTextDelete(mIndex, getText().toString());
////利用上文OnTextViewChangeListener对KEYCODE_DEL按键情况的删除函数进行删除
return true;
}
} else {
Log.d(TAG, "OnTextViewChangeListener was not seted");
//出现其他情况进行报错,文档修改监听器未被建立
}
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);
//当错误发生及当{@link KeyEvent#KEYCODE_ENTER}时添加新文本
} else {
Log.d(TAG, "OnTextViewChangeListener was not seted");////其他情况报错,文档的改动监听器并没有建立
}
break;
default:
break;
}
return super.onKeyUp(keyCode, event);
//回溯至前面函数继续执行父类的其他按键弹起的事件
}
@Override
//函数功能:当焦点发生变化时,会自动调用该方法来处理焦点改变的事件
// * 参数focused表示触发该事件的View是否获得了焦点当该控件获得焦点时Focused等于true否则等于false。
// direction表示焦点移动的方向用数值表示
// Rect表示在触发事件的View的坐标系中前一个获得焦点的矩形区域即表示焦点是从哪里来的。如果不可用则为null
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
if (mOnTextViewChangeListener != null) //判断监听器是否建立
{
if (!focused && TextUtils.isEmpty(getText())) //截取焦点并且判断文本是否为空
{
mOnTextViewChangeListener.onTextChange(mIndex, false);
//mOnTextViewChangeListener子函数置false隐藏事件选项
} else {
mOnTextViewChangeListener.onTextChange(mIndex, true);
//mOnTextViewChangeListener子函数置true显示事件选项
}
}
super.onFocusChanged(focused, direction, previouslyFocusedRect);
//回溯至前面函数继续执行父类的其他焦点变化事件
}
@Override
//函数意义:生成上下文菜单
protected void onCreateContextMenu(ContextMenu menu) {
if (getText() instanceof Spanned) //判断文本是否存在
{
int selStart = getSelectionStart();
int selEnd = getSelectionEnd();
//获取开始位置和截至位置
int min = Math.min(selStart, selEnd);
int max = Math.max(selStart, selEnd);
//计算开始到结尾的最大值和最小值
final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class);
//设置url信息范围值
if (urls.length == 1) {
int defaultResId = 0;
for(String schema: sSchemaActionResMap.keySet()) //获取计划表中的所有key值
{
if(urls[0].getURL().indexOf(schema) >= 0) //若url可以添加则在添加后将defaultResId置为key所映射的值
{
defaultResId = sSchemaActionResMap.get(schema);
break;
}
}
if (defaultResId == 0) //defaultResId == 0则说明url并没有添加任何东西所以置为连接其他SchemaActionResMap的值
{
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);//根据文本进行按键设置
return true;
}
});
}
}
super.onCreateContextMenu(menu);
//回溯至前面函数继续执行父类的其他菜单创建的事件
}
}