解决设置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后长按冲突的问题的更多相关文章

  1. android 布局 使用 viewPager 时,如何解决 和 子页面 长按滑动 冲突问题

    使用 viewPager 时,如何解决 和 子页面 长按滑动 冲突问题. 我的问题原型: 这个问题,我相信遇到的人会比较少,我是在 一个 viewPager 中,其中 一个 fragment 中实现了 ...

  2. Windows10用fiddler抓包Android应用(解决手机设置代理后无法上网,设置只抓app包)

    1.环境准备 1.电脑上安装fiddler 2.手机和电脑在同一个局域网内 2.设置 1.fiddler>Tools>Fiddler Options>Connections 勾选Al ...

  3. catalina.sh设置JAVA_HOME后还无法解决更换JDK有关问题

    catalina.sh设置JAVA_HOME后还无法解决更换JDK问题 表示linux已经安装默认的JDK,需要查找配置文件,更换JDK路径为指定的路径 在root用户下 使用echo $PATH 查 ...

  4. uwp - RichEditBox 解决设置字体样式后滚动条自动回滚顶部的问题

    原文:uwp - RichEditBox 解决设置字体样式后滚动条自动回滚顶部的问题 开发中碰到一个问题,当RichEditBox输入的文本达到一定行数的时候,滚动条此时位于底部,改变文本样式(如字体 ...

  5. 解决Button设置disabled后无法执行后台代码问题

    一.开始调式下面的程序,发现Button在js中设置disabled后无法执行后台代码(btnsave_Click)问题 <asp:Button ID="btnsave" r ...

  6. Android——MeasureSpec学习 - 解决ScrollView嵌套ListView和GridView冲突的方法

      原文地址:http://blog.csdn.net/yuhailong626/article/details/20639217   在自定义View和ViewGroup的时候,我们经常会遇到int ...

  7. Loadrunner解决启动浏览器后页面显示空白

    Loadrunner解决启动浏览器后页面显示空白 2018年5月20日,今天照常打开Loadrunner准备学习,在录制的时候却出现了一个问题,浏览器可以启动,但是程序页面缺是加载不出来,主要症状体现 ...

  8. 【转载】解决k8s中的长连接负载均衡问题

    原文链接:一流铲屎官二流程序员[解决k8s中的长连接负载均衡问题] 长连接与短连接: 简介 长连接是指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测 ...

  9. 子div设置float后导致父div无法自动撑开的问题

    子div设置float后会导致父div无法自动撑开 原因:内部的DIV因为float:left之后,就丢失了clear:both和display:block的样式,所以外部的DIV不会被撑开. 以下是 ...

随机推荐

  1. 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.错误原因 由于在导出文件时,要将导出的文件压缩到压缩 ...

  2. Linux显示列出块设备

    Linux显示列出块设备 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOI ...

  3. 异常-----freemarker.core.ParseException: Token manager error

    一,案例一 1.1.错误描述 freemarker.core.ParseException: Token manager error: freemarker.core.TokenMgrError: L ...

  4. Excel VBA TextBox控件的滚动条不能刷新

    问题:Excel中Textbox控件以及Form里的Textbox控件,当直接填充的内容很长时,滚动条不能实时刷新. 现象: 修改后: 原因: 虽然已经向Textbox的Text里设置了内容,但此时T ...

  5. spring整合JMS

    浏览博客时看到大神写的,直接转载过来收藏了.原文地址:http://elim.iteye.com/blog/1893038

  6. 【BZOJ2748】音量调节(动态规划)

    [BZOJ2748]音量调节(动态规划) 题面 Description 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都要改变一次音量.在演出开始之前,他已经 ...

  7. 【BZOJ1975】【SDOI2010】魔法猪学院(搜索,A*,贪心)

    我已经沉迷于粘贴题目地址了... 题解 很显然的贪心呀, 就是一定是最短的若干条路径的长度 所以,不断拓展k短路就可以了 至于怎么用A* 评估函数f(x)=dis[x]+g[x] 其中,dis是到N号 ...

  8. anaconda的fish shell支持

    最近在用fish shell,但是无法使用conda的activate命令来激活环境.官方给的有解决方案 https://github.com/conda/conda/blob/5b97a96d78e ...

  9. wireshark抓包看ECN

    由于实验需要,要统计ECN信息.为了验证拓扑中是否真的有ECN信息,用了wireshark进行抓包查看. 网上找到的相关有用资料有:http://blog.csdn.net/u011414200/ar ...

  10. oracle使用中的一些问题

    一.设置自增主键(假设表的主键名为:company_id) 1)创建序列(company_autoinc): maxvalue start increment nocache; 2)创建触发器(com ...