当前位置: 首页IT技术 → 自定义可复制的textview

自定义可复制的textview

更多

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

  46 return flag;

  47 }

  48 49 @Override

  50 protected void onCreateContextMenu(ContextMenu menu) {

  51 super.onCreateContextMenu(menu);

  52 if (isInputMethodTarget()) {

  53 menu.removeItem(android.R.id.switchInputMethod);

  54 }

  55 }

  56 57 // textview的点击捕捉

  58 // 如果双击textview选中了具体文字,则使cursor可见

  59 int cursorStart = -1;

  60 61 @Override

  62 public boolean onTouchEvent(MotionEvent event) {

  63 boolean flag = super.onTouchEvent(event);

  64 if (event.getAction() == MotionEvent.ACTION_DOWN && hasSelection()) {

  65 if (cursorStart == -1) {// 由于点击选中文字后,再点击其他位置,第一次点击时显示的hasSelection依然为true,这样一来cursor会依然还在,为了避免这种情况,我这里多对selectionStart进行了一次验证66

   setCursorVisible(true);

  67 cursorStart = getSelectionStart();

  68 } else {

  69 setCursorVisible(false);

  70 cursorStart = -1;

  71 }

  72 }

  73 return flag;

  74 }75

  76 // 当按返回键取消文字复制时,使cursor再次不可见

  77 @Override

  78 public boolean onKeyDown(int keyCode, KeyEvent event) {

  79 boolean flag = super.onKeyDown(keyCode, event);

  80 if (!hasSelection()) {

  81 setCursorVisible(false);

  82 cursorStart = -1;

  83 }

  84 return flag;

  85 }

  86 87 }

   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 //点击menu中的选定item的具体处理方法,捕捉点击文本复制、剪切等按钮的动作

  31 //如果要在点击复制按钮之后取消该textview的cursor可见性的具体监听写在这里

  32 @Override

  33 public boolean onTextContextMenuItem(int id) {

  34 setCursorVisible(true);

  35 boolean flag;

  36 if(id!=android.R.id.switchInputMethod){

  37 flag =super.onTextContextMenuItem(id);

  38 }else{

  39 setCursorVisible(false);

  40 return false;

  41 }

  42 if(id==android.R.id.copy){

  43 setCursorVisible(false);

  44 }

  45 return flag;

  46 }

  47 @Override

  48 protected void onCreateContextMenu(ContextMenu menu) {

  49 super.onCreateContextMenu(menu);

  50 if (isInputMethodTarget()) {

  51 menu.removeItem(android.R.id.switchInputMethod);

  52 }

  53 }

  54 55 //textview的点击捕捉

  56 //如果双击textview选中了具体文字,则使cursor可见

  57 int cursorStart=-1;

  58 @Override

  59 public boolean onTouchEvent(MotionEvent event) {

  60 boolean flag = super.onTouchEvent(event);

  61 if(event.getAction()==MotionEvent.ACTION_DOWN&&hasSelection()){

  62 if(cursorStart==-1){//由于点击选中文字后,再点击其他位置,第一次点击时显示的hasSelection依然为true,这样一来cursor会依然还在,为了避免这种情况,我这里多对selectionStart进行了一次验证63

  setCursorVisible(true);

  64 cursorStart=getSelectionStart();

  65 }else{

  66 setCursorVisible(false);

  67 cursorStart=-1;

  68 }

  69 }

   70 return flag;

  71 }

  72 //当按返回键取消文字复制时,使cursor再次不可见

  73 @Override

  74 public boolean onKeyDown(int keyCode, KeyEvent event) {

  75 boolean flag =super.onKeyDown(keyCode, event);

  76 if(!hasSelection()){

  77 setCursorVisible(false);

  78 }

  79 return flag;

  80 }81

  82 83 }

热门评论
最新评论
昵称:
表情: 高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲
字数: 0/500 (您的评论需要经过审核才能显示)