用过EditText的都知道,EditText有个特点,当在里面长按的时
候,会出现一个ContextMenu,提供了选择文字,复制,剪切等功能。有时候,我们会想,如果不出现这个ContextMenu,直接就在view
上选择文字,那多美好啊。相信很多人抱有这样的想法,很不幸,我也是。于是我就研究了一下EditText和TextView的代码,然后将这个问题解决
了。
网上很多资料都说,要选择一段文字,只需要用Selection.getSelectionStart()和
Selection.getSelectionEnd()确定选择的文字的头和尾,然后加颜色就行。简直是胡扯啊,我敢说这样的代码根本就没有经过验证,
就发到网上了,然后一大堆人互相转载,结果导致误导了很多人,杯具
啊!!
好,我们来分析一下解决办法。
TextView是很多View的基类,如Button、EditText都是继承自他,所以EditText里面的代码很少。我们看一下
EditText的源码,有一个Override的getDefaultEditable方法,看名字的意思是是否可编辑,这个方法直接返回true。还
有一个getDefaultMovementMethod方法,它返回的是ArrowKeyMovementMethod.getInstance(),
通过查看ArrowKeyMovementMethod的源码,基本确定这个方法就是弹出ContextMenu和轨迹球监听的“元凶”。
下面,我们自己做一个view来打造自己的EditText。
我取名TextPage,继承EditText,在里面覆盖getDefaultEditable和getDefaultMovementMethod。
-
@Override
-
public
boolean
getDefaultEditable(){
-
return
false
;
-
}
-
@Override
-
protected
MovementMethodgetDefaultMovementMethod(){
-
return
null
;
-
}
@Override
public boolean getDefaultEditable() {
return false;
}
@Override
protected MovementMethod getDefaultMovementMethod() {
return null;
}
现在测试一下,发现长按没反应了,所料不错,就是getDefaultMovementMethod方法控制了ContextMenu。
看一下ArrowKeyMovementMethod的代码,里面提供了KeyEvent、轨迹球事件onTrackballEvent和touch事件
onTouchEvent的处理。这些事件在何处调用的呢?我们看看TextView的onTouchEvent、onTrackballEvent和
onKeyEvent方法里面就明白了,在这些事件回调中调用了ArrowKeyMovementMethod里面的这些方法。
还有个问题,ContextMenu在哪里触发的?这个问题,用过ContextMenu的都知道,view里面要使用ContextMenu,需要覆盖
一个onCreateContextMenu方法,然后在里面创建ContextMenu的各个选项。在TextView里面找
onCreateContextMenu,果然有,里面定义了选择、复制、粘贴等选项。
既然找到了这个,那么我们就可以进一步分析选择是如何做到的。
onCreateContextMenu只是创建菜单,那么菜单点击之后,触发了什么呢?onCreateContextMenu里面定义了一个
MenuHandler对象,然后作为参数传递给setOnMenuItemClickListener,找到MenuHandler,发现里面的
onMenuItemClick返回的是onTextContextMenuItem函数,找到onTextContextMenuItem,OMG,终
于找到点击menu触发的函数了。但是里面貌似没有关键的东西,选择的部分不在这里。那么,就应该在上面所说的那些事件里面了。
重点分析ArrowKeyMovementMethod的onTouchEvent方法。发现一个重要的方法getLayout(),然后获取一个Layout对象,通过x和y坐标知道当前字符串的offset位置。
那么,问题就可以完美的解决了。你可以点击任何地方然后拖动,释放之后,中间的文字就会被选中,so beautiful!
-
import
android.content.Context;
-
import
android.graphics.Color;
-
import
android.text.Layout;
-
import
android.text.Selection;
-
import
android.view.ContextMenu;
-
import
android.view.Gravity;
-
import
android.view.MotionEvent;
-
import
android.widget.EditText;
-
-
-
-
-
public
class
TextPage
extends
EditText{
-
private
int
off;
-
-
public
TextPage(Contextcontext){
-
super
(context);
-
initialize();
-
}
-
-
private
void
initialize(){
-
setGravity(Gravity.TOP);
-
setBackgroundColor(Color.WHITE);
-
}
-
-
@Override
-
protected
void
onCreateContextMenu(ContextMenumenu){
-
-
}
-
-
@Override
-
public
boolean
getDefaultEditable(){
-
return
false
;
-
}
-
-
@Override
-
public
boolean
onTouchEvent(MotionEventevent){
-
int
action=event.getAction();
-
Layoutlayout=getLayout();
-
int
line=
0
;
-
switch
(action){
-
case
MotionEvent.ACTION_DOWN:
-
line=layout.getLineForVertical(getScrollY()+(int
)event.getY());
-
off=layout.getOffsetForHorizontal(line,(int
)event.getX());
-
Selection.setSelection(getEditableText(),off);
-
break
;
-
case
MotionEvent.ACTION_MOVE:
-
case
MotionEvent.ACTION_UP:
-
line=layout.getLineForVertical(getScrollY()+(int
)event.getY());
-
int
curOff=layout.getOffsetForHorizontal(line,(
int
)event.getX());
-
Selection.setSelection(getEditableText(),off,curOff);
-
break
;
-
}
-
return
true
;
-
}
-
}
分享到:
相关推荐
Android textview 文字中间加上图片
android实现TextView文字部分渐变色;LinearGradientFontSpan SpannableString
主要介绍了Android实现在TextView文字过长时省略部分或滚动显示的方法,结合实例形式分析了Android中TextView控件文字显示及滚动效果相关操作技巧,需要的朋友可以参考下
Android实现TextView文字滚动
android TextView android TextView
多条新闻的title横向滚动播放,并可点击。
自定义textview,长按不会弹出系统的复制和全选
旋转TextView文字显示方向,可参考学习一下。
android textview 文字排版 换行
有时候看到原型图上要求图片和文字对齐,但是直接使用TextView的话总是有一段空白,这里直接继承TextView重写onDraw方法去掉上下边距,但是简单粗暴,导致只能显示文字,没有TextView其他的功能了。
Android中继承TextView实现文字的跑马灯效果,详细了解请移步http://blog.csdn.net/zxc514257857/article/details/70184606
Android SpannableString实现TextView不同大小文字居中显示。
Android自定义TextView实现动态的文字效果
一个自定义的android的翻转textview,效果很不错的
通过textview设置状态选择
Android 为textView增加边框效果,这又是一个初级的Android文字布局示例,今天是为TextView文字框增加一个外边框,可实现在画布上画边框的功能,在填充方面,你还可使用不透明的9.png和透明的9.png,带边框的...
Android流式TextView,类似文字标签。
Android 一个TextView中设置不同字体大小和颜色
textview文字翻滚动画,向下向上动画,消息轮播
本文实例讲述了Android TextView实现垂直滚动效果的方法。分享给大家供大家参考,具体如下: 在TextView中,如果文本很长,可能需要实现垂直滚动显示文本的效果。这里需要在XML布局文件中为TextView设置如下几个属性...