欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android自定義可點(diǎn)擊的ImageSpan并在TextView中內(nèi)置View

 更新時(shí)間:2017年11月22日 11:10:27   作者:丙丁  
這篇文章主要為大家詳細(xì)介紹了Android自定義可點(diǎn)擊的ImageSpan并在TextView中內(nèi)置"View",具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

有的時(shí)候可能想在TextView中添加一些圖片,比如下圖,發(fā)短信輸入聯(lián)系人時(shí),要把聯(lián)系人號碼換成一個(gè)圖片,但這個(gè)圖片無法用固定的某張圖,而是根據(jù)內(nèi)容進(jìn)行定制的,這更像一個(gè)view。

 

當(dāng)然,如果你不是view而是固定的圖片,比如發(fā)信息時(shí)用表情圖片替代特殊符號,那么實(shí)現(xiàn)起來會(huì)更加簡單。又或許,你希望這個(gè)圖片是可點(diǎn)擊的。這里,筆者要介紹的就是怎么用一個(gè)自定義的ImageSpan來實(shí)現(xiàn)在文本里插入可點(diǎn)擊的圖片或View。

在此之前,如果你還不了解SpannableString.setSpan(),不了解LinkMovementMethod是什么,建議先看下筆者的解析TextView中的URL等指定特殊字符串與點(diǎn)擊事件

首先,因?yàn)镮mageSpan沒有繼承ClickableSpan,因此沒有 onClick()方法。所以我寫了個(gè)ClickableImageSpan 。 

public abstract class ClickableImageSpan extends ImageSpan {
 public ClickableImageSpan(Drawable b) {
  super(b);
 }

 public abstract void onClick(View view);
}

同時(shí),我們發(fā)現(xiàn)google提供的LinkMovementMethod只會(huì)執(zhí)行ClickableSpan的onClick()方法.下面是LinkMovementMethod的onTouchEvent()的源碼。這個(gè)方法是在我們點(diǎn)擊Spanned的時(shí)候響應(yīng)。

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) {
     link[0].onClick(widget);
    } else if (action == MotionEvent.ACTION_DOWN) {
     Selection.setSelection(buffer,
           buffer.getSpanStart(link[0]),
           buffer.getSpanEnd(link[0]));
    }

    return true;
   } else {
    Selection.removeSelection(buffer);
   }
  }

  return super.onTouchEvent(widget, buffer, event);
 }

發(fā)現(xiàn)這個(gè)方法其實(shí)就是通過坐標(biāo)找到相應(yīng)的Span。然后,當(dāng)link數(shù)組不為空時(shí),將會(huì)得到span并執(zhí)行他的onClick()方法。這里我們注意到了這一句代碼 

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

這說明該方法只獲得了ClickableSpan,因?yàn)槿绻覀冎苯邮褂孟到y(tǒng)的LinkMovementMethod類,是無法讓ImageSpan響應(yīng)點(diǎn)擊事件的。。因?yàn)槲覀冎?,ImageSpan沒有繼承ClickableSpan。所以,筆者寫了一個(gè)ClickableMovementMethod

public class ClickableMovementMethod extends LinkMovementMethod {

 private static ClickableMovementMethod sInstance;

 public static ClickableMovementMethod getInstance() {
  if (sInstance == null) {
   sInstance = new ClickableMovementMethod();
  }
  return sInstance;
 }

 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);
   ClickableImageSpan[] imageSpans = buffer.getSpans(off, off, ClickableImageSpan.class);

   if (link.length != 0) {
    if (action == MotionEvent.ACTION_UP) {
     link[0].onClick(widget);
    } else if (action == MotionEvent.ACTION_DOWN) {
     Selection.setSelection(buffer,
       buffer.getSpanStart(link[0]),
       buffer.getSpanEnd(link[0]));
    }

    return true;
   } else if (imageSpans.length != 0) {
    if (action == MotionEvent.ACTION_UP) {
     imageSpans[0].onClick(widget);
    } else if (action == MotionEvent.ACTION_DOWN) {
     Selection.setSelection(buffer,
       buffer.getSpanStart(imageSpans[0]),
       buffer.getSpanEnd(imageSpans[0]));
    }

    return true;
   } else {
    Selection.removeSelection(buffer);
   }
  }

  return false;
 }
}

只是做了很小的改動(dòng),這樣,這個(gè)類既可以支持ClickableSpan也可以支持我們自己寫的ClickableImageSpan。

到此為止,一個(gè)可點(diǎn)擊的ImageSpan就完成了。剩下的步驟就跟實(shí)現(xiàn)文字樣式的方式一樣,首先new一個(gè)SpannableString傳入文本,然后找到你需要放置ImageSpan的位置(一般使用正則表達(dá)式),接著new一個(gè)ClickableImageSpan傳入圖片,通過SpannableString的setSpan()方法傳入ClickableImageSpan對象。最后別忘了TextView調(diào)用setMovementMethod時(shí),傳入的是我們的ClickableMovementMethod.getInstance()方法。具體代碼實(shí)現(xiàn)參照文字樣式那邊的,稍作修改即可。具體的筆者不再貼這部分的代碼了。

那么,如果我們不是傳一個(gè)簡單的圖片,而是需要顯示一個(gè)定制的View,應(yīng)該怎么做呢。其實(shí)只要把View轉(zhuǎn)化成Drawable就好,下面是主要的實(shí)現(xiàn)代碼:

 private BitmapDrawable createDrawble(Context ctx, String content) {
 View view = LayoutInflater.from(ctx).inflate(R.layout.viewt, null);
 ((TextView) view.findViewById(R.id.tv_content)).setText(content);
 int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
 view.measure(spec, spec);
 view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
 Bitmap b = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
 Canvas c = new Canvas(b);
 c.translate(-view.getScrollX(), -view.getScrollY());
 view.draw(c);
 view.setDrawingCacheEnabled(true);
 Bitmap cacheBmp = view.getDrawingCache();
 Bitmap viewBmp = cacheBmp.copy(Bitmap.Config.ARGB_8888, true);
 view.destroyDrawingCache();
 return new BitmapDrawable(ctx.getResources(), viewBmp);
 }

 public void filter(Spannable sp) {
 /**
  .....此處省略.
 **/
 BitmapDrawable bd = createDrawble(tv.getContext(), sp.toString); bd.setBounds(0, 0, bd.getIntrinsicWidth(), bd.getIntrinsicHeight());
 MyClickableImageSpan span = new MyClickableImageSpan(bd,text);
 sp.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
 }

createDrawble()方法是通過View的getDrawingCache()方法將一個(gè)View轉(zhuǎn)化成BItmap,然后在獲得BitmapDrawable 后別忘了調(diào)用setBounds(),這個(gè)方法是決定圖片的大小,如果不設(shè)置,那么圖片長寬都為0! 當(dāng)然,你如果嫌顯示的效果太大或太小,也可以通過這個(gè)方法調(diào)整圖片大小。其他步驟相信大家看過筆者的 解析TextView中的URL等指定特殊字符串與點(diǎn)擊事件 ,實(shí)現(xiàn)起來應(yīng)該是沒有困難的。因此筆者不再贅述了。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android車載空調(diào)系統(tǒng)(HVAC)開發(fā)方法分析

    Android車載空調(diào)系統(tǒng)(HVAC)開發(fā)方法分析

    HVAC?全稱:供暖通風(fēng)與空氣調(diào)節(jié)(Heating?Ventilation?and?Air?Conditioning),用戶可以通過他來控制整個(gè)汽車的空調(diào)系統(tǒng),是汽車中非常重要的一個(gè)功能,汽車的空調(diào)HMI雖然并不復(fù)雜,但是大多都是用符號來表示功能,必須理解空調(diào)的各個(gè)符號表示的含義
    2023-12-12
  • Android ListView UI組件使用說明

    Android ListView UI組件使用說明

    這篇文章主要介紹了Android ListView UI組件使用說明,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Flutter之可滾動(dòng)組件子項(xiàng)緩存?KeepAlive詳解

    Flutter之可滾動(dòng)組件子項(xiàng)緩存?KeepAlive詳解

    這篇文章主要為大家詳細(xì)介紹了Flutter之可滾動(dòng)組件子項(xiàng)緩存?KeepAlive,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • Android簡單實(shí)現(xiàn)屏幕下方Tab菜單的方法

    Android簡單實(shí)現(xiàn)屏幕下方Tab菜單的方法

    這篇文章主要介紹了Android簡單實(shí)現(xiàn)屏幕下方Tab菜單的方法,簡單分析了Android實(shí)現(xiàn)tab菜單所涉及的界面布局及功能相關(guān)操作技巧,需要的朋友可以參考下
    2016-08-08
  • Android Jetpack導(dǎo)航組件Navigation創(chuàng)建使用詳解

    Android Jetpack導(dǎo)航組件Navigation創(chuàng)建使用詳解

    這篇文章主要為大家介紹了Android Jetpack導(dǎo)航組件Navigation創(chuàng)建及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • ToolBar使用方法詳解

    ToolBar使用方法詳解

    這篇文章主要為大家詳細(xì)介紹了Android中ToolBar的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Android API編程之Assets文件操作示例

    Android API編程之Assets文件操作示例

    這篇文章主要介紹了Android API編程之Assets文件操作,結(jié)合實(shí)例形式分析了Android針對Assets文件夾下的文件操作相關(guān)技巧,需要的朋友可以參考下
    2017-08-08
  • Android實(shí)現(xiàn)空心圓角矩形按鈕的實(shí)例代碼

    Android實(shí)現(xiàn)空心圓角矩形按鈕的實(shí)例代碼

    頁面上有時(shí)會(huì)用到背景為空心圓角矩形的Button,可以通過xml繪制出來。這篇文章主要介紹了Android實(shí)現(xiàn)空心圓角矩形按鈕的實(shí)例代碼,需要的朋友參考下吧
    2017-01-01
  • Android Bitmap壓縮方式分析

    Android Bitmap壓縮方式分析

    這篇文章主要介紹了Android Bitmap壓縮方式分析的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • Android RecyclerView實(shí)現(xiàn)下拉刷新和上拉加載更多

    Android RecyclerView實(shí)現(xiàn)下拉刷新和上拉加載更多

    這篇文章主要為大家詳細(xì)介紹了Android RecyclerView實(shí)現(xiàn)下拉刷新和上拉加載更多,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-02-02

最新評論