最近要實現圖文混排的需求,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());