解决设置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. Flex中TitleWindow传值

    Flex中TitleWindow传值 1.设计思路 (1)新建一个DataGrid,在其中最后一列加入三个按钮:新增.修改和删除: (2)点击新增按钮,可以将表格新增一行: (3)单击"修改 ...

  2. Openstack_后端存储平台Ceph

    框架图 介绍 一种为优秀的性能.可靠性和可扩展性而设计的统一的.分布式文件系统 特点 CRUSH算法 Crush算法是ceph的两大创新之一,简单来说,ceph摒弃了传统的集中式存储元数据寻址的方案, ...

  3. jQuery.proxy()的用法

    一:参考范文一 第一次接触jQuery.proxy()时感觉这个方法不实用,不明白它到底是个什么意思.今天来将jQuery官网上的解释进行一下翻译,顺便添加自己的理解和一些示例.proxy也可称为代理 ...

  4. Java虚拟机的锁优化

    1 锁偏向.当现成请求一个对象锁时,如果获得锁,则该对象锁进入偏向模式,当该线程再次请求该对象的锁时,无需再做任何同步操作. 可通过在Java虚拟机中开启参数-XX:+UseBasedLock开启偏向 ...

  5. php+sqlServer 2008R2 PHPstudy下数据库环境搭建

    简要:小主从事PHP二年,期间一直做后台;在过程中遇到一个奇葩的组合就是PHP+sqlServer应用场景,希望能够跟各位PHP大神分享和学习探索,如果有不对或者好的建议告知下:*~*! 一.下载sq ...

  6. [LOJ2230][BJOI2014]大融合

    题面戳我 sol LCT维护子树size. 开一个数组\(sz_i\)表示一个节点的所有虚儿子的size和,\(sum_i\)表示以一个节点为根的子树的\(size\)和,可见\(sz_u=\sum_ ...

  7. Bzoj2134:单选错位

    题面 Bzoj Sol 第\(i\)道题选对的概率就是\(\frac{min(a[i-1], a[i])}{a[i]*a[i-1]}\) # include <bits/stdc++.h> ...

  8. Bzoj3992:[SDOI2015]序列统计

    题面 Bzoj Sol pts 1 大暴力很简单,\(f[i][j]\)表示到第\(i\)个位置,前面积的模为\(j\)的方案 然后可以获得\(10\)分的好成绩 # include <bits ...

  9. [AH/HNOI2017]礼物

    \[推推公式,即求\Sigma^{n}_{i=1} (x_{i+k}-y_i+c)^2最小,c范围为[-m, m]\] \[拆开,就是\Sigma x_i^2 + \Sigma y_i^2 + n * ...

  10. 近期安卓与IOS招聘面试有感

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.你总是想一步登天,却不知道路是一步步走出来的 大概是放年假前一个月开始招聘吧,陆陆续续到目前为止安卓面试10几个,IOS面试了15个左右,本以为 ...