方法
*方法一:重寫LinkMovementMethod
*方法二:設(shè)置ImageSpan的同時(shí),同一位置設(shè)置一個(gè)ClickableSpan
FAQ
去掉圖片的點(diǎn)擊選中狀態(tài)
注釋掉如下代碼
Selection.setSelection(buffer,
buffer.getSpanStart(imageSpans[0]),
buffer.getSpanEnd(imageSpans[0]));
假設(shè)連續(xù)兩張圖片,點(diǎn)擊TextView中的第二個(gè)span,但是實(shí)際響應(yīng)的是第一個(gè)span
Android ClickableSpan 光標(biāo)選擇問(wèn)題,有需要的朋友可以參考下。
最近因項(xiàng)目需求,使用到CloudEditText 來(lái)實(shí)現(xiàn)文字輸入,并且需要點(diǎn)擊改變ImageSpan背景,使用軟鍵盤刪除鍵進(jìn)行操作
先說(shuō)明一下原理,CloudEditText 是使用 SpannableString 來(lái)進(jìn)行插入帶有樣式的文字,主要分3層:
1.SpannableString 必須有字符串傳入,不然后續(xù)的插入ImageSpan 與 ClickableSpan 都會(huì)出現(xiàn)數(shù)組越界問(wèn)題,因?yàn)闆](méi)有字符串的插入,EditText本身就是空的
SpannableString spannableString=new SpannableString(getText())
2.ImageSpan 插入drawable 到 對(duì)應(yīng)字符串長(zhǎng)度的區(qū)間
spannableString.setSpan(imageSpan,start,end,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
3.ClickableSpan 插入同ImageSpan 相同的區(qū)間
spannableString.setSpan(clickSpan,start,end,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
想要ClickableSpan 觸發(fā)點(diǎn)擊事件,edittext.setMovementMethod(LinkMovementMethod.getInstance()) 這句話是必須要加的
說(shuō)說(shuō)這里邊會(huì)遇到的一些坑,
1.點(diǎn)擊事件位置偏移問(wèn)題
問(wèn)題主要出在LinkMovementMethod 這個(gè)類中的OnTouchEvent 方法中,源碼里邊是這樣寫的 int off =layout.getOffsetForHorizontal(line,x) ,經(jīng)查閱此方法返回值是最接近手指觸摸位置的偏移量,這里就會(huì)出現(xiàn)一個(gè)問(wèn)題,當(dāng)手指觸摸到某個(gè)字符最前邊位置時(shí),光標(biāo)會(huì)選中在字符前邊,此時(shí)去刪除的話,必然會(huì)刪掉前一個(gè)字符。
當(dāng)然在字符上觸摸,因?yàn)槲恢脜^(qū)間小,用戶不太會(huì)關(guān)注,即使選錯(cuò)了,再選一次也無(wú)所謂;但是在點(diǎn)擊span的時(shí)候,出現(xiàn)這種情況就無(wú)法原諒了,因?yàn)閟pan相當(dāng)于把字符放大化了,這個(gè)時(shí)候點(diǎn)擊span的前邊位置,竟然會(huì)選中前一個(gè)span ,簡(jiǎn)直無(wú)法直視了
在遍查Google 和 Stack Overflow之后,竟然沒(méi)有找到解決方案,此時(shí)滿腦子都是修改源碼的思想,可是layout.getOffsetForHorizontal(line,x) 方法中設(shè)計(jì)到layout 中其他部分的源碼,全部修改工作量太大了。沒(méi)辦法,先硬著頭皮去看看layout的源碼,結(jié)果讓我找到一個(gè)可以解決問(wèn)題的方法,layout.getPrimaryHorizontal(off) ,根據(jù)位置獲取x軸的位移,這就好辦了,因?yàn)槭种赣|摸的位置是一定的,對(duì)比一下,就可以解決問(wèn)題了,方案如下:
float xLeft=layout.getPrimaryHorizontal(off);
if(xLeft<x){
off+=1;
}else{
off-=1;
}
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);