中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android如何實現自定義可點擊的ImageSpan并在TextView中內置View

發布時間:2021-06-30 11:04:18 來源:億速云 閱讀:383 作者:小新 欄目:移動開發

這篇文章主要介紹Android如何實現自定義可點擊的ImageSpan并在TextView中內置View,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

有的時候可能想在TextView中添加一些圖片,比如下圖,發短信輸入聯系人時,要把聯系人號碼換成一個圖片,但這個圖片無法用固定的某張圖,而是根據內容進行定制的,這更像一個view。

Android如何實現自定義可點擊的ImageSpan并在TextView中內置View 

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

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

首先,因為ImageSpan沒有繼承ClickableSpan,因此沒有 onClick()方法。所以我寫了個ClickableImageSpan 。 

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

 public abstract void onClick(View view);
}

同時,我們發現google提供的LinkMovementMethod只會執行ClickableSpan的onClick()方法.下面是LinkMovementMethod的onTouchEvent()的源碼。這個方法是在我們點擊Spanned的時候響應。

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);
 }

發現這個方法其實就是通過坐標找到相應的Span。然后,當link數組不為空時,將會得到span并執行他的onClick()方法。這里我們注意到了這一句代碼 

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

這說明該方法只獲得了ClickableSpan,因為如果我們直接使用系統的LinkMovementMethod類,是無法讓ImageSpan響應點擊事件的。。因為我們知道,ImageSpan沒有繼承ClickableSpan。所以,筆者寫了一個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;
 }
}

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

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

那么,如果我們不是傳一個簡單的圖片,而是需要顯示一個定制的View,應該怎么做呢。其實只要把View轉化成Drawable就好,下面是主要的實現代碼:

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

以上是“Android如何實現自定義可點擊的ImageSpan并在TextView中內置View”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

云浮市| 南涧| 兴城市| 绩溪县| 林州市| 金溪县| 辉南县| 天峻县| 英山县| 土默特右旗| 道孚县| 四川省| 读书| 陆川县| 安平县| 乐陵市| 西盟| 汾阳市| 水富县| 景宁| 保定市| 定陶县| 樟树市| 黄冈市| 济南市| 桐柏县| 治县。| 常宁市| 盐城市| 曲阳县| 乌苏市| 泸西县| 巫溪县| 漠河县| 曲周县| 福贡县| 泰安市| 门源| 宿松县| 临漳县| 泸定县|