最近准备写一款阅读相关的应用,希望内部的文字都可以实现完整的可复制性,这对于信息分享的而言至关重要。类似人人网客户端那样内部文字完全不可复制,信息只能在站内共享的方式让我很郁闷,所以我就想来实现一个类似uc网页页面内容皆可复制的textview。
在仔细看了一段时间textview和edittext的代码之后,我发现其实如果要求不高的话,我们完全可以在edittext的基础上来实现一个符合我所述要求的textview。具体实现过程不难,有两大主要问题点。
- 首先 ,edittext已经很好的实现了相关文本复制的操作,但是我希望不能在其内部输入文字,不能对内部的文字进行删减。
- 其次,我们需要解决edittext游标cursor的问题,使其在我们需要的时候出现,不需要的时候gone去一边。
第一个问题很简单,我们只需要在应用到该edittext的地方属性android: seteditable=”false”就可以了。关键难点在于第二点,我们如果想当然地认为只要设置setCursorVisible=”false”就能满足需求的话就大错特错了。我们需要清晰地了解cursor什么时候会出现,什么时候不会消失。
实际测试过程我发现edittext中的代码量很少,大部分的功能其实都在textview中被实现了,而导致,导致我们在长按edittext时弹出复制剪切选择框的关键方法如下:
View Code
1 @Override
2 protected MovementMethod getDefaultMovementMethod() {
3 // TODO Auto-generated method stub
4 return super.getDefaultMovementMethod();
5 }
树藤摸瓜,我们可以看到与复制相关的几个关键类是:
ArrowKeyMovementMethod和Selection。
当然纯粹为了实现我这儿的功能的话这两个类都暂时不用去动。
我们只需要重写几个edittext里的方法就可以,具体代码如下:
View Code
1 package com.hebin.activity;
2
3 import android.content.Context;
4 import android.text.Selection;
5 import android.text.method.MovementMethod;
6 import android.util.AttributeSet;
7 import android.view.ContextMenu;
8 import android.view.KeyEvent;
9 import android.view.MotionEvent;
10 import android.widget.EditText;
11
12 /**
13 * @author heb
14 * @class_name MyTextView.java
15 * @date 2012-3-22
16 */
17 public class MyTextView extends EditText {
18
19 public MyTextView(Context context, AttributeSet attrs) {
20 super(context, attrs);
21 }
22
23 // 长按弹出文本选择框menu的关键方法:可以选择复制、剪切等等功能,视该textview的具体实现而定
24 // 如果希望不弹出这个menu界面,只要把这个方法返回空就ok
25 @Override
26 protected MovementMethod getDefaultMovementMethod() {
27 // TODO Auto-generated method stub
28 return super.getDefaultMovementMethod();
29 }
30
31 // 点击menu中的选定item的具体处理方法,捕捉点击文本复制、剪切等按钮的动作
32 // 如果要在点击复制按钮之后取消该textview的cursor可见性的具体监听写在这里
33 @Override
34 public boolean onTextContextMenuItem(int id) {
35 setCursorVisible(true);
36 boolean flag;
37 if (id != android.R.id.switchInputMethod) {
38 flag = super.onTextContextMenuItem(id);
39 } else {
40 setCursorVisible(false);
41 return false;
42 }
43 if (id == android.R.id.copy) {
44 setCursorVisible(false);
45 cursorStart = -1;
46 }
47 return flag;
48 }
49
50 @Override
51 protected void onCreateContextMenu(ContextMenu menu) {
52 super.onCreateContextMenu(menu);
53 if (isInputMethodTarget()) {
54 menu.removeItem(android.R.id.switchInputMethod);
55 }
56 }
57
58 // textview的点击捕捉
59 // 如果双击textview选中了具体文字,则使cursor可见
60 int cursorStart = -1;
61
62 @Override
63 public boolean onTouchEvent(MotionEvent event) {
64 boolean flag = super.onTouchEvent(event);
65 if (event.getAction() == MotionEvent.ACTION_DOWN && hasSelection()) {
66 if (cursorStart == -1) {// 由于点击选中文字后,再点击其他位置,第一次点击时显示的hasSelection依然为true,这样一来cursor会依然还在,为了避免这种情况,我这里多对selectionStart进行了一次验证
67 setCursorVisible(true);
68 cursorStart = getSelectionStart();
69 } else {
70 setCursorVisible(false);
71 cursorStart = -1;
72 }
73 }
74 return flag;
75 }
76
77 // 当按返回键取消文字复制时,使cursor再次不可见
78 @Override
79 public boolean onKeyDown(int keyCode, KeyEvent event) {
80 boolean flag = super.onKeyDown(keyCode, event);
81
82 setCursorVisible(false);
83 cursorStart = -1;
84 return flag;
85 }
86
87 }
88
89 }