具體Demo見GitHub:RichTextDemo
無圖無真相吱晒,下圖中的所有內(nèi)容全在一個TextView
中展示甸饱。
主要由SpannableString.setSpan()
和ImageSapn
實現(xiàn)TextView
顯示圖片功能,核心代碼如下:
String text = "圖文混排內(nèi)容";
SpannableString spannableString = new SpannableString(text);
Drawable drawable = 來自本地或者網(wǎng)絡(luò)的圖片;
ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
spannableString.setSpan(imageSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);
其中spannableString.setSpan(imageSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
將text
中圖片對應的文本叹话,替換成相應的文圖片偷遗,實現(xiàn)圖文混排。ImageSpan
中需傳入的Drawable
可以讀取本地圖片驼壶,或者從網(wǎng)絡(luò)獲取氏豌。
詳細代碼如下,具體說明看代碼注釋:
其中簡書中正則表達式顯示有問題热凹,正確的為
private void setRichText(Context context) {
float imageSize = textView.getTextSize();
//圖文混排的text泵喘,這里用"[]"標示圖片
String text = "這是圖文混排的例子:\n網(wǎng)絡(luò)圖片:"
+ "[http://hao.qudao.com/upload/article/20160120/82935299371453253610.jpg][http://b.hiphotos.baidu.com/zhidao/pic/item/d6ca7bcb0a46f21f27c5c194f7246b600d33ae00.jpg]"
+ "\n本地圖片:" + "[哈哈][淚][多肉][多肉2]";
SpannableString spannableString = new SpannableString(text);
//匹配"[(除了']'任意內(nèi)容)]"的正則表達式,獲取網(wǎng)絡(luò)圖片和本地圖片替換位置
//簡書中正則表達式顯示有問題碌嘀,正確如上圖
Pattern pattern = Pattern.compile("\\[[^\\]]+\\]");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
ImageSpan imageSpan;
//匹配的內(nèi)容涣旨,例如[http://hao.qudao.com/upload/article/20160120/82935299371453253610.jpg]或[哈哈]
String group = matcher.group();
if (group.contains("http")) {
//網(wǎng)絡(luò)圖片
//獲取圖片url(去掉'['和']')
String url = group.substring(1, group.length() - 1);
//異步獲取網(wǎng)絡(luò)圖片
Drawable drawableFromNet = new URLImageParser(textView, context, (int) imageSize).getDrawable(url);
imageSpan = new ImageSpan(drawableFromNet, ImageSpan.ALIGN_BASELINE);
//設(shè)置網(wǎng)絡(luò)圖片
spannableString.setSpan(imageSpan, matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
//本地圖片
if (localIconMap.get(group) != null) {
//獲取本地圖片Drawable
Drawable drawableFromLocal = context.getResources().getDrawable(localIconMap.get(group));
//獲取圖片寬高比
float ratio = drawableFromLocal.getIntrinsicWidth() * 1.0f / drawableFromLocal.getIntrinsicHeight();
//設(shè)置圖片寬高
drawableFromLocal.setBounds(0, 0, (int) (imageSize * ratio), (int)(imageSize));
imageSpan = new ImageSpan(drawableFromLocal, ImageSpan.ALIGN_BASELINE);
//設(shè)置本地圖片
spannableString.setSpan(imageSpan, matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
textView.setText(spannableString);
}
private void initData(Context context) {
ResourceUtils utils = ResourceUtils.getInstance(context);
localIconMap = new HashMap<>();
//獲取本地圖片標示對應的圖片ID(例如[哈哈]對應的R.drawable.haha)
localIconMap.put(utils.getString("haha"), utils.getDrawableId("haha"));
localIconMap.put(utils.getString("lei"), utils.getDrawableId("lei"));
localIconMap.put(utils.getString("duorou"), utils.getDrawableId("duorou"));
localIconMap.put(utils.getString("duorou2"), utils.getDrawableId("duorou2"));
}
其中URLImageParser代碼如下:
public class URLImageParser {
private Context mContext;
private TextView mTextView;
private int mImageSize;
/**
*
* @param textView 圖文混排TextView
* @param context
* @param imageSize 圖片顯示高度
*/
public URLImageParser(TextView textView, Context context, int imageSize) {
mTextView = textView;
mContext = context;
mImageSize = imageSize;
}
public Drawable getDrawable(String url) {
URLDrawable urlDrawable = new URLDrawable();
new ImageGetterAsyncTask(mContext, url, urlDrawable).execute(mTextView);
return urlDrawable;
}
public class ImageGetterAsyncTask extends AsyncTask<TextView, Void, Bitmap> {
private URLDrawable urlDrawable;
private Context context;
private String source;
private TextView textView;
public ImageGetterAsyncTask(Context context, String source, URLDrawable urlDrawable) {
this.context = context;
this.source = source;
this.urlDrawable = urlDrawable;
}
@Override
protected Bitmap doInBackground(TextView... params) {
textView = params[0];
try {
//下載網(wǎng)絡(luò)圖片,以下是使用Picasso和Glide獲取網(wǎng)絡(luò)圖片例子股冗,也可以其他方式下載網(wǎng)絡(luò)圖片
// 使用Picasso獲取網(wǎng)絡(luò)圖片Bitmap
return Picasso.with(context).load(source).get();
// 使用Glide獲取網(wǎng)絡(luò)圖片Bitmap(使用Glide獲取圖片bitmap還有待研究)
// return Glide.with(context).load(source).asBitmap().fitCenter().into(mImageSize * 3, mImageSize * 3).get();
} catch (Exception e) {
return null;
}
}
@Override
protected void onPostExecute(final Bitmap bitmap) {
try {
//獲取圖片寬高比
float ratio = bitmap.getWidth() * 1.0f / bitmap.getHeight();
Drawable bitmapDrawable = new BitmapDrawable(context.getResources(), bitmap);
bitmapDrawable.setBounds(0, 0, (int) (mImageSize * ratio), mImageSize);
//設(shè)置圖片寬霹陡、高(這里傳入的mImageSize為字體大小,所以止状,設(shè)置的高為字體大小烹棉,寬為按寬高比縮放)
urlDrawable.setBounds(0, 0, (int) (mImageSize * ratio), mImageSize);
urlDrawable.drawable = bitmapDrawable;
//兩次調(diào)用invalidate才會在異步加載完圖片后,刷新圖文混排TextView怯疤,顯示出圖片
urlDrawable.invalidateSelf();
textView.invalidate();
} catch (Exception e) {
/* Like a null bitmap, etc. */
}
}
}
}
URLDrawable代碼如下:
public class URLDrawable extends BitmapDrawable {
// the drawable that you need to set, you could set the initial drawing
// with the loading image if you need to
protected Drawable drawable;
@Override
public void draw(Canvas canvas) {
// override the draw to facilitate refresh function later
if(drawable != null) {
drawable.draw(canvas);
}
}
}
ResourceUtils代碼如下:
public class ResourceUtils {
private static ResourceUtils resourceUtils;
private static Context context;
private Resources resources;
private String packageName;
public static ResourceUtils getInstance(Context context) {
if (resourceUtils == null) {
synchronized (ResourceUtils.class) {
resourceUtils = new ResourceUtils(context);
}
}
return resourceUtils;
}
public ResourceUtils(Context context) {
this.context = context;
resources = context.getResources();
packageName = context.getPackageName();
}
public int getStringId(String name) {
try {
//對應values:strings.xml文件
return this.resources.getIdentifier(name, "string", packageName);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
public String getString(String name) {
try {
return this.resources.getString(getStringId(name));
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public int getDrawableId(String name) {
try {
//對應drawable-***文件夾中的圖片
return this.resources.getIdentifier(name, "drawable", packageName);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
}
具體Demo見GitHub:RichTextDemo
參考:
Android之Glide獲取圖片Path浆洗、Bitmap用法
Display images on Android using TextView and Html.ImageGetter asynchronously?
Android HTML ImageGetter as AsyncTask
Android ImageGetter images overlapping text