对TextVIew中特定字符串设定onTouchEvent方法

上面是Iphone备忘录的图,笔者之前接到一个需求是实现点击文本框里的数字,弹出一个类似上图的按钮,显示出复制,要求是这个按钮的位置必须是根据你点击的位置进行定位(为什么这么说,是因为我们不可能把按钮放在你点击的地方那样显示效果不太好,一般都是在点击的位置再往上一定的尺寸)。关于这个需求,在脑海里速度分析下,就能找出几个点,首先,我们是要过滤TextView里的字符串,找出所有的数字,这个用正则很好实现,然后要给每串数字一个点击事件,这个可以通过SpannableString.setSpan和TextView.setMovementMethod(MovementMethod movement)来实现,实现起来大概是这样。
private void init() {
tvMain.setMovementMethod(LinkMovementMethod.getInstance());
SpannableString s = new SpannableString(CONTENT);
filterNumber(s);
tvMain.setText(s);
}
private static final String REG = "\\d+";
public class TextClickableSpan extends ClickableSpan {
private String text;
public TextClickableSpan(String text) {
this.text = text;
}
@Override
public void onClick(View view) {
//do something
}
}
private void filterNumber(Spannable s) {
Matcher m = Pattern.compile(REG).matcher(s.toString());
while (m.find()) {
String text = m.group();
TextClickableSpan span = new TextClickableSpan(text);
s.setSpan(span,m.start(),m.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
当我想在onClick()里做处理的时候,我发现我无法得到我当前点击的位置,这让我想起来一个叫做onTouchEvent的方法,可惜ClickSpan里没这方法。于是我就自定义了一个TouchableSpan类
public abstract class TouchableSpan extends CharacterStyle implements UpdateAppearance {
@Override
public void updateDrawState(TextPaint tp) {
tp.setColor(tp.linkColor);
tp.setUnderlineText(true);
}
public abstract void onActionUp(View view,MotionEvent event);
}
有两个方法,第一个方法是我直接从ClickableSpan里抄过来的,很明显,这是用来设置样式的,分别是颜色和下划线。第二个方法是onActionUp(View view,MotionEvent event);这个事我自定义的,用来响应我们点击松手时的事件,在这里,我传入了一个MotionEvent,这样我们就能获得到点击的坐标了。但是又出现一个问题,LinkMovementMethod里只会调用ClickableSpan的onClick()方法。所以我最后又写了一个TouchableMovementMethod继承LinkMovementMethod类
public class TouchableMovementMethod extends LinkMovementMethod {
private static TouchableMovementMethod sInstance;
public static TouchableMovementMethod getInstance() {
if (sInstance == null) {
sInstance = new TouchableMovementMethod();
}
return sInstance;
}
public boolean onTouchEvent(TextView widget, Spannable buffer,
MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
TouchableSpan [] touchSpans = buffer.getSpans(off, off, TouchableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
} else if (touchSpans.length != 0) {
if (action == MotionEvent.ACTION_UP) {
touchSpans[0].onClick(widget,event);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(touchSpans[0]),
buffer.getSpanEnd(touchSpans[0]));
}
return true;
} else {
Selection.removeSelection(buffer);
}
}
return false;
}
}
代码很简单,我只是重写了onTouchEvent方法(这个方法是LinkMovementMethod 本来就有的),我稍作了一些修改,让他既可以支持原有的ClickableSpan,又可以支持我们的TouchableSpan。这样就能很好的实现无法获得点击坐标的难题了,,
相关博文:自定义可点击的ImageSpan并在TextView中内置“View“
对TextVIew中特定字符串设定onTouchEvent方法的更多相关文章
- java中两字符串比较--compareTo方法
java.lang.String.compareTo() 方法比较两个字符串的字典,比较是基于字符串中的每个字符的Unicode值 String n1 = "1"; String ...
- JavaScript中去除字符串空格的方法
语法 string.trim() 参数值 无 返回值 类型:string 描述:返回移除头尾空格的字符串 技术细节 JavaScript版本: ECMAScript 5 去除字符串左右两端的空格,在v ...
- C# 从 UTF-8 流中读取字符串的正确方法
我们下面的代码是从一个流 stream 中读取 UTF-8 编码的字符串.我们可以先考虑一下其中存在的潜在问题. string ReadString(Stream stream) { var sb = ...
- MyEclipse如何查找指定工程下所有或指定文件中特定字符串并且可进行批量替换
查找操作步骤:(1)在myEclipse里菜单选择-Search-Search(快捷键:ctrl+h);(2)在弹出对话框中选File Search选项,然后在第一个文本框中输入“要查找的字符串”(为 ...
- python中的字符串内置方法小结
#!/usr/local/bin/python3 # -*- coding:utf-8 -*- ''' name="my wife is mahongyan" ---------- ...
- linux查看日志中特定字符串以及前后信息内容命令
在项目实施过程中,我们经常会查看日志,更是经常会根据某些特地字符串去查找日志内容. 下面就是日志查找命令: 1.查询字符串命令: cat fileName|grep '要查找的字符串' 实例:cat ...
- 在SQL中 给字符串补0方法
--第一种方法SELECT RIGHT('00000'+CAST(ID AS nvarchar(50)),5) FROM dbo.TableName --左边补0,如 00001,00039 SELE ...
- C#中判断字符串相等的方法
可以使用如下方式: 1. String.Compare(str1, str2) == 0 或者 str1.CompareTo(str2) == 0 2. str1.Equals(str2) 或者 ...
- C#替换文件中特定字符串,按照原来的编码格式保存
private void button1_Click(object sender, EventArgs e) { var txt1 = "E:\\Temp\\local"; str ...
随机推荐
- Android Studio3.3中Cannot resolve symbol ActivityTestRule
最近在看<Android编程权威指南>,在Windows10下安装了Android Studio3.3,边看编练习书中的例子程序,看到第21章""音频播放与单元测试&q ...
- kafka的简介
1. kafka是一个分布式消息队列.具有高性能.持久化.多副本备份.横向扩展能力.生产者往队列里写消息,消费者从队列里取消息进行业务逻辑.一般在架构设计中起到解耦.削峰.异步处理的作用. 1.1 b ...
- idea下远程debug配置
一. 背景: 在测试工作中,为方便发现代码中的逻辑问题,尝试使用远程debug模式,在测试过程中走查代码,不仅可以辅助测试减少与开发的沟通成本,更便于了解业务提升测试深度. 二. 配置方式: 1. 调 ...
- Pytest参数传递
import pytest@pytest.fixture()def login_r(open_browser):#调用login时,发现需要先打开浏览器,所以改成先打开浏览器,在登陆 print('输 ...
- 带你看懂LayoutInflater中inflate方法
关于inflate问题,我想很多人多多少少都了解一点,网上也有很多关于这方面介绍的文章,但是枯燥的理论或者翻译让很多小伙伴看完之后还是一脸懵逼,so,我今天想通过三个案例来让小伙伴彻底的搞清楚这个东东 ...
- android5.1 隐藏状态栏
修改frameworks/base/core/res/res/values/dimens.xml文件中 <!-- Height of the status bar --> <!-- ...
- HDU-4747 二分+线段树
题意:给出长度为n的序列,问任两个区间的mex运算结果的总和. 解法:直接讲线段树做法:我们注意到mex(1,1),mex(1,2),mex(1,3)...mex(1,i)的结果是单调不减的,那么我们 ...
- appium1.7的使用
1.安装成功后,双击图标启动appium 2.输入host:0.0.0.0 ,port:4723,点击start server,启动appium,如下图所示,启动成功 3.点击搜索图标,打开定位工具I ...
- macOS添加字体
打开macOS的Applications文件夹: 双击其中的Font Book: 把下载的字体解压后的_文件夹_ 拖进来,字体就安装好了.
- posix_rpi_common.cmake学习
# This file is shared between posix_rpi_native.cmake 这个文件在posix_rpi_native.cmake和posix_rpi_cross.cma ...