自由选择TextView的文字
2011-05-13 21:50
302 查看
用过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。
Java代码
1.@Override
2.public boolean getDefaultEditable() {
3. return false ;
4.}
5.@Override
6.protected MovementMethod getDefaultMovementMethod() {
7. return null ;
8.}
现在测试一下,发现长按没反应了,所料不错,就是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!
Java代码
1.import android.content.Context;
2.import android.graphics.Color;
3.import android.text.Layout;
4.import android.text.Selection;
5.import android.view.ContextMenu;
6.import android.view.Gravity;
7.import android.view.MotionEvent;
8.import android.widget.EditText;
9.
10./**
11. * @author chroya
12. */
13.public class TextPage extends EditText {
14. private int off; //字符串的偏移值
15.
16. public TextPage(Context context) {
17. super (context);
18. initialize();
19. }
20.
21. private void initialize() {
22. setGravity(Gravity.TOP);
23. setBackgroundColor(Color.WHITE);
24. }
25.
26. @Override
27. protected void onCreateContextMenu(ContextMenu menu) {
28. //不做任何处理,为了阻止长按的时候弹出上下文菜单
29. }
30.
31. @Override
32. public boolean getDefaultEditable() {
33. return false ;
34. }
35.
36. @Override
37. public boolean onTouchEvent(MotionEvent event) {
38. int action = event.getAction();
39. Layout layout = getLayout();
40. int line = 0 ;
41. switch (action) {
42. case MotionEvent.ACTION_DOWN:
43. line = layout.getLineForVertical(getScrollY()+ (int )event.getY());
44. off = layout.getOffsetForHorizontal(line, (int )event.getX());
45. Selection.setSelection(getEditableText(), off);
46. break ;
47. case MotionEvent.ACTION_MOVE:
48. case MotionEvent.ACTION_UP:
49. line = layout.getLineForVertical(getScrollY()+(int )event.getY());
50. int curOff = layout.getOffsetForHorizontal(line, ( int )event.getX());
51. Selection.setSelection(getEditableText(), off, curOff);
52. break ;
53. }
54. return true ;
55. }
56.}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wanqieddy521/archive/2011/03/29/6286961.aspx
网上很多资料都说,要选择一段文字,只需要用Selection.getSelectionStart()和Selection.getSelectionEnd()确定选择的文字的头和尾,然后加颜色就行。简直是胡扯啊,我敢说这样的代码根本就没有经过验证,就发到网上了,然后一大堆人互相转载,结果导致误导了很多人,杯具 啊!!
好,我们来分析一下解决办法。
TextView是很多View的基类,如Button、EditText都是继承自他,所以EditText里面的代码很少。我们看一下EditText的源码,有一个Override的getDefaultEditable方法,看名字的意思是是否可编辑,这个方法直接返回true。还有一个getDefaultMovementMethod方法,它返回的是ArrowKeyMovementMethod.getInstance(),通过查看ArrowKeyMovementMethod的源码,基本确定这个方法就是弹出ContextMenu和轨迹球监听的“元凶”。
下面,我们自己做一个view来打造自己的EditText。
我取名TextPage,继承EditText,在里面覆盖getDefaultEditable和getDefaultMovementMethod。
Java代码
1.@Override
2.public boolean getDefaultEditable() {
3. return false ;
4.}
5.@Override
6.protected MovementMethod getDefaultMovementMethod() {
7. return null ;
8.}
现在测试一下,发现长按没反应了,所料不错,就是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!
Java代码
1.import android.content.Context;
2.import android.graphics.Color;
3.import android.text.Layout;
4.import android.text.Selection;
5.import android.view.ContextMenu;
6.import android.view.Gravity;
7.import android.view.MotionEvent;
8.import android.widget.EditText;
9.
10./**
11. * @author chroya
12. */
13.public class TextPage extends EditText {
14. private int off; //字符串的偏移值
15.
16. public TextPage(Context context) {
17. super (context);
18. initialize();
19. }
20.
21. private void initialize() {
22. setGravity(Gravity.TOP);
23. setBackgroundColor(Color.WHITE);
24. }
25.
26. @Override
27. protected void onCreateContextMenu(ContextMenu menu) {
28. //不做任何处理,为了阻止长按的时候弹出上下文菜单
29. }
30.
31. @Override
32. public boolean getDefaultEditable() {
33. return false ;
34. }
35.
36. @Override
37. public boolean onTouchEvent(MotionEvent event) {
38. int action = event.getAction();
39. Layout layout = getLayout();
40. int line = 0 ;
41. switch (action) {
42. case MotionEvent.ACTION_DOWN:
43. line = layout.getLineForVertical(getScrollY()+ (int )event.getY());
44. off = layout.getOffsetForHorizontal(line, (int )event.getX());
45. Selection.setSelection(getEditableText(), off);
46. break ;
47. case MotionEvent.ACTION_MOVE:
48. case MotionEvent.ACTION_UP:
49. line = layout.getLineForVertical(getScrollY()+(int )event.getY());
50. int curOff = layout.getOffsetForHorizontal(line, ( int )event.getX());
51. Selection.setSelection(getEditableText(), off, curOff);
52. break ;
53. }
54. return true ;
55. }
56.}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wanqieddy521/archive/2011/03/29/6286961.aspx
相关文章推荐
- Android自由选择TextView的文字
- Android开发:自由选择TextView的文字
- Android开发:自由选择TextView的文字
- Android自由选择TextView的文字
- Android自由选择TextView的文字
- Android自由选择TextView的文字
- Android自由选择TextView的文字
- Android开发:自由选择TextView的文字
- Android自由选择TextView的文字
- Android自由选择TextView的文字
- Android自由选择TextView的文字
- Android开发:自由选择TextView的文字
- Android开发:自由选择TextView的文字
- android WebView 长按自由复制文字,进入文字选择模式
- Android 自定义Textview实现文字两端对齐功能和长按自由选择文字弹出自定义ActionMenu功能(二)自定义ActionMenu
- Android 自定义Textview实现文字两端对齐功能和长按自由选择文字弹出自定义ActionMenu功能(一)
- Android选择TextView的文字
- 各个浏览器中鼠标位置的属性 offsetX layerX PageX clientX (自由拖动框,防止文字选中)
- 【菜鸟学安卓】- TextView的文字大小 setTextSize 和 getTextSize 设置
- android 用textview实现文字滚动效果