最近准备写一款阅读相关的应用,希望内部的文字都可以实现完整的可复制性,这对于信息分享的而言至关重要。类似人人网客户端那样内部文字完全不可复制,信息只能在站内共享的方式让我很郁闷,所以我就想来实现一个类似uc网页页面内容皆可复制的textview。

在仔细看了一段时间textview和edittext的代码之后,我发现其实如果要求不高的话,我们完全可以在edittext的基础上来实现一个符合我所述要求的textview。具体实现过程不难,有两大主要问题点。

  • 首先 ,edittext已经很好的实现了相关文本复制的操作,但是我希望不能在其内部输入文字,不能对内部的文字进行删减。
  • 其次,我们需要解决edittext游标cursor的问题,使其在我们需要的时候出现,不需要的时候gone去一边。

第一个问题很简单,我们只需要在应用到该edittext的地方属性android: seteditable=”false”就可以了。关键难点在于第二点,我们如果想当然地认为只要设置setCursorVisible=”false”就能满足需求的话就大错特错了。我们需要清晰地了解cursor什么时候会出现,什么时候不会消失。

实际测试过程我发现edittext中的代码量很少,大部分的功能其实都在textview中被实现了,而导致,导致我们在长按edittext时弹出复制剪切选择框的关键方法如下:

 




android开发 TextView复制 安卓textview可复制_android

android开发 TextView复制 安卓textview可复制_android_02

View Code


1 @Override
2     protected MovementMethod getDefaultMovementMethod() {
3         // TODO Auto-generated method stub
4         return super.getDefaultMovementMethod();
5     }



树藤摸瓜,我们可以看到与复制相关的几个关键类是:

ArrowKeyMovementMethod和Selection。

当然纯粹为了实现我这儿的功能的话这两个类都暂时不用去动。

我们只需要重写几个edittext里的方法就可以,具体代码如下:




android开发 TextView复制 安卓textview可复制_android

android开发 TextView复制 安卓textview可复制_android_02

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  }