专栏首页封碎Android自由选择TextView的文字 博客分类: Android AndroidUP

Android自由选择TextView的文字 博客分类: Android AndroidUP

      用过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 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;

/**
 * @author chroya
 */
public class TextPage extends EditText {
	private int off; //字符串的偏移值

	public TextPage(Context context) {
		super(context);
		initialize();
	}

	private void initialize() {
		setGravity(Gravity.TOP);
		setBackgroundColor(Color.WHITE);
	}
	
	@Override
    protected void onCreateContextMenu(ContextMenu menu) {
		//不做任何处理,为了阻止长按的时候弹出上下文菜单
	}
	
	@Override
	public boolean getDefaultEditable() {
		return false;
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		int action = event.getAction();
		Layout layout = 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;
	}
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 程序员你伤不起

    这本书以随笔的形式描述了作者的2005年至2011年的一些个人经历。主要是工作、生活当中的感悟,以及一些技术思想的分享。作者的文笔比较调侃和幽默,不需要花费很大...

    张子阳
  • 非暴力沟通

    知道这本书是一次在和朋友跑步时听她提起,因为我有去京东上面看图书畅销榜的习惯,无意中又看到了这本书,朋友正好看完了,就借来读一下。

    张子阳
  • 想成为「不那么差」的程序员,离不开这个 buff

    一周前,我分享了篇文章《如何成为一位「不那么差」的程序员》,当时主要是从硬技能和软实力两方面分享经验,今天我想做一点补充:其实,做一名不那么差的程序员,也离不开...

    zhisheng
  • 程序员们,转变你的思维方式吧!

    笔者已经工作两年多了,在这里我想谈下关于程序员关于职业的思维方式。对于职业的思维方式,决定了一个人的选择和成就。建立一个正确的思维方式,有利于我们主动管理自己的...

    栋先生
  • 【本体】电机偏差值

    EdenChen
  • 沟通学TCP握手,等于谋财害命

    TCP之所以有这个三次握手协议有很多历史原因。但是最主要的我认为是网络基础架构不稳定。因为不稳定,所以我们需要多次向对方表示或者等待对方反复确认“我爱你”...

    用户1564362
  • 读《学习之道》— 深入理解拖延的习惯

    神经模型从频繁的练习中产生,他们自动联结形成组块,而组块和习惯有着密切的联系。习惯可以帮我们节省力气,它能为我们的大脑腾出空间进行别的活动。以倒车为例,开始时迎...

    Ewall
  • 转录因子(TF)的作用方式

    转录因子主要有3种作用方式调控基因表达: TF既可以结合在DNA临近的增强子也可以结合在启动子玉玉。和TF有关的基因转录既可以上调也可以下调,TF通过以下几个...

    Y大宽
  • 快速在组合中查找重复和遗失的元素

    望月从良
  • 聊聊架构

    这本书原本是发表在InfoQ上的专栏文章,原名叫做《架构漫谈》,因为反响良好,所以编撰成书。全书没有涉及过多的具体技术,更像是一些随笔。

    张子阳

扫码关注云+社区

领取腾讯云代金券