欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ImageSpan添加点击事件

程序员文章站 2022-05-25 21:46:09
...

方法

*方法一:重写LinkMovementMethod
*方法二:设置ImageSpan的同时,同一位置设置一个ClickableSpan

FAQ

去掉图片的点击选中状态

注释掉如下代码

 Selection.setSelection(buffer,
 buffer.getSpanStart(imageSpans[0]),
 buffer.getSpanEnd(imageSpans[0]));

假设连续两张图片,点击TextView中的第二个span,但是实际响应的是第一个span

Android ClickableSpan 光标选择问题,有需要的朋友可以参考下。

最近因项目需求,使用到CloudEditText 来实现文字输入,并且需要点击改变ImageSpan背景,使用软键盘删除键进行操作

先说明一下原理,CloudEditText 是使用 SpannableString 来进行插入带有样式的文字,主要分3层:

1.SpannableString 必须有字符串传入,不然后续的插入ImageSpan 与 ClickableSpan 都会出现数组越界问题,因为没有字符串的插入,EditText本身就是空的

SpannableString spannableString=new SpannableString(getText())

2.ImageSpan 插入drawable 到 对应字符串长度的区间

spannableString.setSpan(imageSpan,start,end,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

3.ClickableSpan 插入同ImageSpan 相同的区间

spannableString.setSpan(clickSpan,start,end,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

想要ClickableSpan 触发点击事件,edittext.setMovementMethod(LinkMovementMethod.getInstance()) 这句话是必须要加的

说说这里边会遇到的一些坑,

1.点击事件位置偏移问题

问题主要出在LinkMovementMethod 这个类中的OnTouchEvent 方法中,源码里边是这样写的 int off =layout.getOffsetForHorizontal(line,x) ,经查阅此方法返回值是最接近手指触摸位置的偏移量,这里就会出现一个问题,当手指触摸到某个字符最前边位置时,光标会选中在字符前边,此时去删除的话,必然会删掉前一个字符。

当然在字符上触摸,因为位置区间小,用户不太会关注,即使选错了,再选一次也无所谓;但是在点击span的时候,出现这种情况就无法原谅了,因为span相当于把字符放大化了,这个时候点击span的前边位置,竟然会选中前一个span ,简直无法直视了

在遍查Google 和 Stack Overflow之后,竟然没有找到解决方案,此时满脑子都是修改源码的思想,可是layout.getOffsetForHorizontal(line,x) 方法中设计到layout 中其他部分的源码,全部修改工作量太大了。没办法,先硬着头皮去看看layout的源码,结果让我找到一个可以解决问题的方法,layout.getPrimaryHorizontal(off) ,根据位置获取x轴的位移,这就好办了,因为手指触摸的位置是一定的,对比一下,就可以解决问题了,方案如下:

float xLeft=layout.getPrimaryHorizontal(off);
if(xLeft<x){
    off+=1;
}else{
    off-=1;
}

ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);

参考

  1. ImageSpan 可点击、图片与设置不一样大
  2. 自定义可点击的ImageSpan并在TextView中内置“View“
  3. Android ClickableSpan 光标选择问题