解决设置clickablespan后长按冲突的问题
解决设置ClickableSpan后长按冲突的问题
问题描述
3月份修改别人代码的时候想要屏蔽TextView的长按事件,发现TextView有重写OnTouchEvent方法,然后在其中加了长按事件的判断,是长按事件则不做任何处理。结果测试发现并没有得到想要的效果,所以继续查看代码,最终发现,代码里对TextView设置了setSpan(new ClickableSpan),导致长按事件无法被我们捕捉到。
分析
因为查看代码是因为添加了setSpan(new ClickableSpan)方法导致长按无法被检测到,所以主要是分析ClickableSpan来寻找解决方法。
ClickableSpan
If an object of this type is attached to the text of a TextView with a movement method of LinkMovementMethod, the affected spans of text can be selected. If selected and clicked, the {@link #onClick} method will be called.
翻译一下:如果这个类型被添加到TextView的text上,并且这个TextView有一个LinkMovementMethod的行为方法,则text可以被选择。如果选择并且点击,则onClick方法会被调用。
就是说ClickanleSpan被设置到TextView的某段text上,点击被设置的text,则会调用ClickanleSpan的onClick方法。
LinkMovementModel
A movement method that traverses links in the text buffer and scrolls if necessary. Supports clicking on links with DPad Center or Enter.
翻译一下:链接文字的行为方法并在需要是滚动。支持DPad中心或输入的链接点击。
查看LInkMovementModel的源码发现,它有一个onTouchEvent方法:
@Override
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[] links = buffer.getSpans(off, off, ClickableSpan.class);
if (links.length != 0) {
if (action == MotionEvent.ACTION_UP) {
links[0].onClick(widget);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(links[0]),
buffer.getSpanEnd(links[0]));
}
return true;
} else {
Selection.removeSelection(buffer);
}
}
return super.onTouchEvent(widget, buffer, event);
}
查看源码发现,它只是处理了ACTION_UP(抬起)与ACTION_DOWN(按下)事件,里面没有处理长按事件,也没有长按事件的接口。
所以解决方法找到了,就是重写LInkMovementModel的onTouchEvent()方法。
解决方法
写一个LinkMovementClickMethod类,继承LinkMovementMethod类,然后重写onTouchEvent()方法。
将源码中的onTouchEvent代码复制过来,加上一个判断,如果点击不是长按,则按照源码的处理方式处理,代码如下:
public class LinkMovementClickMethod extends LinkMovementMethod {
private long lastClickTime;
private static final long CLICK_DELAY = 500l;
@Override
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);
if (link.length != 0) {
============================修改的部分==============================
if (action == MotionEvent.ACTION_UP) {
if (System.currentTimeMillis() - lastClickTime < CLICK_DELAY) {
link[0].onClick(widget);
}
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
lastClickTime = System.currentTimeMillis();
}
============================修改的部分==============================
return true;
} else {
Selection.removeSelection(buffer);
}
}
return super.onTouchEvent(widget, buffer, event);
}
public static LinkMovementClickMethod getInstance() {
if (null == sInstance) {
sInstance = new LinkMovementClickMethod();
}
return sInstance;
}
private static LinkMovementClickMethod sInstance;
}
这样长按事件就被排除在外,问题得以解决。
解决设置clickablespan后长按冲突的问题的更多相关文章
- android 布局 使用 viewPager 时,如何解决 和 子页面 长按滑动 冲突问题
使用 viewPager 时,如何解决 和 子页面 长按滑动 冲突问题. 我的问题原型: 这个问题,我相信遇到的人会比较少,我是在 一个 viewPager 中,其中 一个 fragment 中实现了 ...
- Windows10用fiddler抓包Android应用(解决手机设置代理后无法上网,设置只抓app包)
1.环境准备 1.电脑上安装fiddler 2.手机和电脑在同一个局域网内 2.设置 1.fiddler>Tools>Fiddler Options>Connections 勾选Al ...
- catalina.sh设置JAVA_HOME后还无法解决更换JDK有关问题
catalina.sh设置JAVA_HOME后还无法解决更换JDK问题 表示linux已经安装默认的JDK,需要查找配置文件,更换JDK路径为指定的路径 在root用户下 使用echo $PATH 查 ...
- uwp - RichEditBox 解决设置字体样式后滚动条自动回滚顶部的问题
原文:uwp - RichEditBox 解决设置字体样式后滚动条自动回滚顶部的问题 开发中碰到一个问题,当RichEditBox输入的文本达到一定行数的时候,滚动条此时位于底部,改变文本样式(如字体 ...
- 解决Button设置disabled后无法执行后台代码问题
一.开始调式下面的程序,发现Button在js中设置disabled后无法执行后台代码(btnsave_Click)问题 <asp:Button ID="btnsave" r ...
- Android——MeasureSpec学习 - 解决ScrollView嵌套ListView和GridView冲突的方法
原文地址:http://blog.csdn.net/yuhailong626/article/details/20639217 在自定义View和ViewGroup的时候,我们经常会遇到int ...
- Loadrunner解决启动浏览器后页面显示空白
Loadrunner解决启动浏览器后页面显示空白 2018年5月20日,今天照常打开Loadrunner准备学习,在录制的时候却出现了一个问题,浏览器可以启动,但是程序页面缺是加载不出来,主要症状体现 ...
- 【转载】解决k8s中的长连接负载均衡问题
原文链接:一流铲屎官二流程序员[解决k8s中的长连接负载均衡问题] 长连接与短连接: 简介 长连接是指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测 ...
- 子div设置float后导致父div无法自动撑开的问题
子div设置float后会导致父div无法自动撑开 原因:内部的DIV因为float:left之后,就丢失了clear:both和display:block的样式,所以外部的DIV不会被撑开. 以下是 ...
随机推荐
- java.util.zip.ZipException:ZIP file must have at least one entry
1.错误描述 java.util.zip.ZipException:ZIP file must have at least one entry 2.错误原因 由于在导出文件时,要将导出的文件压缩到压缩 ...
- Linux显示列出块设备
Linux显示列出块设备 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOI ...
- 异常-----freemarker.core.ParseException: Token manager error
一,案例一 1.1.错误描述 freemarker.core.ParseException: Token manager error: freemarker.core.TokenMgrError: L ...
- Excel VBA TextBox控件的滚动条不能刷新
问题:Excel中Textbox控件以及Form里的Textbox控件,当直接填充的内容很长时,滚动条不能实时刷新. 现象: 修改后: 原因: 虽然已经向Textbox的Text里设置了内容,但此时T ...
- spring整合JMS
浏览博客时看到大神写的,直接转载过来收藏了.原文地址:http://elim.iteye.com/blog/1893038
- 【BZOJ2748】音量调节(动态规划)
[BZOJ2748]音量调节(动态规划) 题面 Description 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都要改变一次音量.在演出开始之前,他已经 ...
- 【BZOJ1975】【SDOI2010】魔法猪学院(搜索,A*,贪心)
我已经沉迷于粘贴题目地址了... 题解 很显然的贪心呀, 就是一定是最短的若干条路径的长度 所以,不断拓展k短路就可以了 至于怎么用A* 评估函数f(x)=dis[x]+g[x] 其中,dis是到N号 ...
- anaconda的fish shell支持
最近在用fish shell,但是无法使用conda的activate命令来激活环境.官方给的有解决方案 https://github.com/conda/conda/blob/5b97a96d78e ...
- wireshark抓包看ECN
由于实验需要,要统计ECN信息.为了验证拓扑中是否真的有ECN信息,用了wireshark进行抓包查看. 网上找到的相关有用资料有:http://blog.csdn.net/u011414200/ar ...
- oracle使用中的一些问题
一.设置自增主键(假设表的主键名为:company_id) 1)创建序列(company_autoinc): maxvalue start increment nocache; 2)创建触发器(com ...