ImageSpan添加点击事件

方法

*方法一:重写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 光标选择问题

推荐阅读更多精彩内容