解决设置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不会被撑开. 以下是 ...
随机推荐
- php xml DOM编码
PHP XML文件编程 一.PHP DOM编程 <?php //1.创建dom对象 $xmldoc=new DOMDocument(); //2.加载xml(指定对哪个xml文件进行操作) $x ...
- Oracle 子程序参数模式,IN,OUT,IN OUT
IN :用于传入参数. 在调用过程的时候,实参传到该过程中. 在过程内部,形参只读且不能更改. 在过程执行完毕,返回调用环境时候,实参到的值也不会改变 --带IN参数的过程,赋值. create or ...
- USB设备驱动概述
USB设备驱动 · )USB Hub:每个USBHost控制器都会自带一个USB Hub,被称为根(Root)Hub.这个根Hub可以接子(Sub)Hub,每个Hub上挂载USB设备.一般PC有8个 ...
- Linux显示进程状态
Linux显示进程状态 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ top top - 19:16:36 up 45 min, 2 users, load ...
- 关于游览器网页标题logo的设置
<link rel="shortcut icon"type="image/x-icon" href="images/favicon.ico&qu ...
- Good Bye 2017 E. New Year and Entity Enumeration
先按照绿点进行分块 第一个绿点和最后一个绿点之后很好处理不说了 两个绿点之间的讨论: 有两种方案 1:红(蓝)点和绿点顺序连接,距离为相邻绿点距离(也就是双倍绿点距离) 2:红(蓝)点和绿点的点阵中寻 ...
- C#的动态链接库和XML配置
今天对昨天的实例进行了改进和提高,将堆排序和冒泡排序封装在一个动态链接库中,提供函数调用和事件委托.此外加入XML进行配置,在XML中存入相关配置信息,提供一个单独的XmlClass对其进行操作,加深 ...
- python实现列表倒叙打印
def func(listNode): listNode.reverse() for i in listNode: print(i) li = [1,2,3,4,5] func(li) 利用pytho ...
- 备库搭建后,进入备库报错psql: FATAL: the database system is starting up
备库搭建后,进入备库报错psql: FATAL: the database system is starting up 原因:备库配置文件没有hot_standby = on mast ...
- ajax 状态码
状态码定义 ... 10 信息1xx ... 10.1 100继续 ... 10.1.1 101交换协议 ... 10.1.2 成功的2xx ... 10.2 200 OK ... 10.2.1 20 ...