TextView + Spanned實現圖文混排以及圖片點擊交互

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

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

我把它封裝成了一個控件,使用的時候只要將它放到xml佈局
下載地址:https://github.com/githubwing/RichTextView

<?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());
發佈了113 篇原創文章 · 獲贊 589 · 訪問量 53萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章