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.
git-xiaomibianqian/other/代码标注/ui/210340165吴堃玮代码标注NoteEditTex...

215 lines
11 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;
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 {//继承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>();//设置映射,将文本内容(电话、网址、邮件)做链接处理
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);
}//在NoteEditActivity进行文本的操作删除进入编辑
/**
* Call by the {@link NoteEditActivity} to delete or add edit text
*/
public interface OnTextViewChangeListener {//接口OnTextViewChangeListener会被NoteEditActivity大量调用其中定义了在编辑文本中delete、点击enter、text改变时的方法
/**
* Delete current edit text when {@link KeyEvent#KEYCODE_DEL} happens
* and the text is null
*/
void onEditTextDelete(int index, String text);//当delete键按下时删除当前编辑的文字块
/**
* Add edit text after current edit text when {@link KeyEvent#KEYCODE_ENTER}
* happen
*/
void onEditTextEnter(int index, String text);//当触发输入文本KeyEvent时增添文本
/**
* Hide or show item option when text change
*/
void onTextChange(int index, boolean hasText);//文字更改时隐藏或显示项目选项
}
private OnTextViewChangeListener mOnTextViewChangeListener;//新建私有变量:文本改变的监听器
public NoteEditText(Context context) {//根据context设置文本
super(context, null);//用super引用父类变量
mIndex = 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) {//view里的函数处理手机屏幕的所有事件。参数event为手机屏幕触摸事件封装类的对象其中封装了该事件的所有信息例如触摸的位置、触摸的类型以及触摸的时间等。该对象会在用户触摸手机屏幕时被创建。
switch (event.getAction()) {//重写屏幕触发事件
case MotionEvent.ACTION_DOWN://更新坐标
int x = (int) event.getX();//更新x值为当前触摸处的x值
int y = (int) event.getY();//更新y值为当前触摸处的y值
x -= getTotalPaddingLeft();//减去左边控件的距离
y -= getTotalPaddingTop();//减去上方控件的距离
x += getScrollX();
y += getScrollY();//加上滚轮滚过的距离
Layout layout = getLayout();//用布局控件layout根据x,y的新值设置新的位置
int line = layout.getLineForVertical(y);//获取纵向行数
int off = layout.getOffsetForHorizontal(line, x);//获取横向偏移量
Selection.setSelection(getText(), off);//更新光标位置
break;
}
return super.onTouchEvent(event);//调用父类当屏幕有Touch事件时此方法就会被调用。
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {//处理用户按下一个键盘按键时会触发 的事件
switch (keyCode) {//根据按键的KeyCode来处理
case KeyEvent.KEYCODE_ENTER://按下回车时,如果mOnTextViewChangeListener存在则返回false
if (mOnTextViewChangeListener != null) {
return false;
}
break;
case KeyEvent.KEYCODE_DEL://删除按键
mSelectionStartBeforeDelete = getSelectionStart();//获取删除文本开始位置
break;
default://其他情况,返回父类的onKeyDown值
break;
}
return super.onKeyDown(keyCode, event);//继续执行父类的其他点击事件
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {//处理用户松开一个键盘按键时会触发的事件
switch(keyCode) {//根据按键的 Unicode 编码值来处理有删除和进入2种操作
case KeyEvent.KEYCODE_DEL://若触发修改且文档不为空则调用前面代码的onEditTextDelete函数进行文本删除
if (mOnTextViewChangeListener != null) {
if (0 == mSelectionStartBeforeDelete && mIndex != 0) {
mOnTextViewChangeListener.onEditTextDelete(mIndex, getText().toString());
return true;//利用上文OnTextViewChangeListener对KEYCODE_DEL按键情况的删除函数进行删除
}
} else {
Log.d(TAG, "OnTextViewChangeListener was not seted");//其他情况报错,文档的改动监听器并没有建立
}
break;
case KeyEvent.KEYCODE_ENTER://若文档改动监听器已建立则获取当前位置和文本并根据获取的信息调用onEditTextEnter函数进行文本增添
if (mOnTextViewChangeListener != null) {
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");//其他情况报错监听器OnTextViewChangeListener并没有建立。
}
break;
default:
break;
}
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);//置false隐藏事件选项
} else {
mOnTextViewChangeListener.onTextChange(mIndex, true);//置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;// 默认的资源ID值为0
for(String schema: sSchemaActionResMap.keySet()) {//获取计划表中所有的key值
if(urls[0].getURL().indexOf(schema) >= 0) {
defaultResId = sSchemaActionResMap.get(schema);
break;
}//若url可以添加则在添加后将defaultResId置为key所映射的值
}
if (defaultResId == 0) {
defaultResId = R.string.note_link_other;
}//defaultResId == 0则说明url并没有添加任何东西所以置为连接其他SchemaActionResMap的值
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);//创建文本菜单
}
}