1. 程式人生 > >TextView + Spanned實現圖文混排以及點選互動

TextView + Spanned實現圖文混排以及點選互動

最近要實現圖文混排的需求,webview過大,所以想到了用SpannableStringBuilder來實現。 不過參考了大量國內文章,大多數是教你如何實現圖文混排,並沒有提及圖片點選互動的。有翻閱了一些國外文章,說的也不是很詳細,於是花費時間鼓搗了一下,最終實現了TextView圖文混排,加點選互動的效果,在這裡給大家分享下以免後來者在此處浪費過多時間。

主要用到的有Spanned ClickSpan ImageSpan ImagerGetter Html 。
先看一下效果圖:
這裡寫圖片描述

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft
="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.wingsofts.richtextview.MainActivity" >
<com.wingsofts.richtextview.RichTextView android:id="@+id/richTextView"
android:layout_width="match_parent" android:layout_height="wrap_content" />
</RelativeLayout>
,然後
  RichTextView richTextView = (RichTextView) findViewById(R.id.richTextView);
    richTextView.setHtml(mTxt,1000,800);
    richTextView.setOnImageClickListener(new RichTextView.ImageClickListener() {
      @Override public void onImageClick(String imageUrl, String[] imageUrls, int position) {
        Toast.makeText(MainActivity.this, "imageUrl :"+imageUrl+"\nimage size:"+imageUrls.length+"\n position:"+position, Toast.LENGTH_SHORT).show();
      }
    });

實現思路

由於後臺是傳來的html,所以可以藉助系統類Html來解析生成Spanned,再將SpannedString轉換為ClickSpan,最終實現圖文混排+圖片互動效果。

後臺先傳來一段html,如下:

String mTxt =
      "<p>\r\n\t<span style=\"font-size:16px;\"><strong>比騰訊還土豪 傳《陰陽師》專案組發60個月工資獎金</strong></span>\r\n</p>\r\n<p>\r\n\t<span style=\"font-size:16px;\">  今日下午一則關於網易《陰陽師》專案組員工發60個月工資的獎金忽然在整個遊戲圈流傳,而以網易遊戲平均10000以上的薪資水平來算,《陰陽師》專案組成員的獎金將達到60萬元以上。"
          + "<img src=\"http://p2.pstatp.com/large/e220006a85a0b689eb8\" width=\"520\" height=\"216\" title=\"上證指數\" alt=\"上證指數\" />在遊戲公司專案組發獎金較為平常,不過能夠達到60個月工資的也就此前盛傳的騰訊LOL專案組曾經打到過,包括幾年之前被業界津津樂道的CF專案組都未曾有過這麼高的規格。根據多家網站的資料和行業平均水平,網易遊戲的平均薪資應該不會低於10000,這筆獎金的總額度可能創遊戲行業有史以來最高。"
          + "</span>\r\n</p>\r\n<p>\r\n\t<span style=\"font-size:16px;\"><br />\r\n</span>\r\n</p>\r\n<p>\r\n\t<span style=\"font-size:16px;\"><img src=\"http://p3.pstatp.com/large/e1d000f89d603327470\" width=\"520\" height=\"216\" title=\"上證指數\" alt=\"上證指數\" />《陰陽師》是網易自研的3D和風卡牌RPG手遊,同時該作也是一款二次元向手遊,遊戲9月2正式上架App Store,9月9日開始全平臺公測,自上架以來該作就開始了傳奇的衝榜之旅,到今天已經高居暢銷榜第二名,僅次於長期包攬第一的同門師兄《夢幻西遊》。\n"
          + "\n"
          + "<img src=\"http://p3.pstatp.com/large/e21000f51e83cb9b1c9\" width=\"520\" height=\"216\" title=\"上證指數\" alt=\"上證指數\" />";
之後利用Html.form()生成Spanned
stringBuilder = (SpannableStringBuilder) Html.fromHtml(source,
        new GlideImageGetter(mContext, Glide.with(mContext), this, false, width, height), null);

注意這裡的第二個引數,是一個ImageGetter型別的介面,這裡直接拿了Glide作者開發的Imagegetter來使用,他的作用是在spanned中載入圖片。

國內的文章大多介紹到這裡,實現了圖文混排。。。然後就沒有然後了。。可是尼瑪我想點選放大啊有沒有。。 莫急,接下來就告訴你們,如何點選互動。

其實就是將Spanned轉換為clickspan,

//從stringBuilder中讀取圖片
mImageSpans = stringBuilder.getSpans(0, stringBuilder.length(), ImageSpan.class);

     //過濾出整個textView的所有圖片
    mImageUrls = new String[mImageSpans.length];
    for (int i = 0; i < mImageSpans.length; i++) {
      mImageUrls[i] = mImageSpans[i].getSource();
    }
    for (int i = 0; i < mImageSpans.length; i++) {

        //獲取圖片span的起尾
      int start = stringBuilder.getSpanStart(mImageSpans[i]);
      int end = stringBuilder.getSpanEnd(mImageSpans[i]);
      final int finalI = i;

      //將span轉化為clickspan
      stringBuilder.setSpan(new ClickableSpan() {
        @Override public void onClick(View widget) {
          if (mImageClickListener != null) {
            mImageClickListener.onImageClick(mImageUrls[finalI], mImageUrls, finalI);
          }
        }
      }, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

嘛。。理論上這樣就可以了,可是事實上,你會發現,點選圖片根本沒鳥反應!!!!!然後我有鼓搗了一會。。發現需要加上一句,才可以。


    setMovementMethod(LinkMovementMethod.getInstance());