工作太忙,不做过多的解释了,核心是用到了 SpannableStringBuilder  Glide  和 Rxjava

直接上代码了,就两个类。

public class ImageSpanAsyncLoad {

    public ImageSpanAsyncLoad() {

    }

    @SuppressLint("StaticFieldLeak")
public void displayTextAndImage(List<SkuDeliveryBean> skuDelivery, final String title, final TextView textView) { if (TextUtils.isEmpty(title)) {
return;
} final StringBuilder stringBuilder;
if (skuDelivery != null && skuDelivery.size() > 0) {
stringBuilder = new StringBuilder(" " + title);
} else {
stringBuilder = new StringBuilder(title);
}
textView.setText(stringBuilder); // List<String> tagPathList = getProductDelivery(skuDelivery);
if (skuDelivery == null || skuDelivery.size() <= 0) {
return;
} // 创建下载任务
List<Observable<ResultTask>> tempTaskList = new ArrayList<>();
for (int i = 0; i < skuDelivery.size(); i++) {
DownloadTask task = new DownloadTask(i, skuDelivery.get(i).getSkuDeliveryUrl());
task.width = skuDelivery.get(i).getWidth();
task.height = skuDelivery.get(i).getHeight();
tempTaskList.add(createDownaloadTask(task));
stringBuilder.insert(0, " ");
} // 合并任务
Observable.mergeDelayError(tempTaskList)
.subscribeOn(Schedulers.newThread())
.unsubscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ResultTask>() { Disposable mD;
List<ResultTask> temp = new ArrayList<>(); @Override
public void onSubscribe(Disposable d) {
mD = d;
} @Override
public void onNext(ResultTask resultTask) {
temp.add(resultTask);
} @Override
public void onError(Throwable e) { } @Override
public void onComplete() {
if (mD != null) {
mD.dispose();
} // 排序
Collections.sort(temp, new Comparator<ResultTask>() {
@Override
public int compare(ResultTask o1, ResultTask o2) {
return o1.position - o2.position;
}
}); // 开始绘制
SpannableStringBuilder sb = new SpannableStringBuilder();
sb.append(stringBuilder.toString());
for (int i = 0; i < temp.size(); i++) {
ResultTask task = temp.get(i);
float radio = (float) SizeUtils.dp2px(task.height) / task.drawable.getIntrinsicHeight();
task.drawable.setBounds(0, 0, (int) (task.drawable.getIntrinsicWidth() * radio), SizeUtils.dp2px(task.height));
CenterAlignImageSpan imageSpan = new CenterAlignImageSpan(task.drawable);
sb.setSpan(imageSpan, i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
textView.setText(sb);
}
}); } // 创建下载任务
private Observable<ResultTask> createDownaloadTask(DownloadTask downloadTask) { Observable<ResultTask> temp; temp = Observable.just(downloadTask)
.observeOn(Schedulers.newThread())
.flatMap(new Function<DownloadTask, ObservableSource<ResultTask>>() {
@Override
public ObservableSource<ResultTask> apply(DownloadTask downloadTask) throws Exception { ResultTask resultTask = new ResultTask();
resultTask.position = downloadTask.position;
resultTask.width = downloadTask.width;
resultTask.height = downloadTask.height; // 下图片
if (downloadTask.drawable != null) {
resultTask.drawable = downloadTask.drawable;
} else {
resultTask.drawable = GlideApp.with(BaseApplication.getInstance())
.asDrawable()
.load(downloadTask.imgUrl)
.submit()
.get();
} return Observable.just(resultTask);
}
}); return temp; } /**
* 设置标签
*
* @param skuDelivery 全球购 次日达 等网络图片
* @param title 标题
* @param textView view
* @param tag 自营非自营等
*/
@SuppressLint("StaticFieldLeak")
public void displayTextAndImage(List<SkuDeliveryBean> skuDelivery, final String title, final TextView textView, final String tag) { if (TextUtils.isEmpty(title)) {
return;
} final StringBuilder stringBuilder;
if (skuDelivery != null && skuDelivery.size() > 0) {
stringBuilder = new StringBuilder(" " + title);
} else {
stringBuilder = new StringBuilder(title);
}
textView.setText(stringBuilder);
// 创建下载任务
List<Observable<ResultTask>> tempTaskList = new ArrayList<>();
int j = 0;
//有标签手动设置drawable
if (!TextUtils.isEmpty(tag)) {
//R.layout.tag是每个标签的布局
View view = LayoutInflater.from(textView.getContext()).inflate(R.layout.tag, null);
TextView tv_tag = view.findViewById(R.id.tv_tag);
tv_tag.setText(tag);
view.setDrawingCacheEnabled(true);
view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
Bitmap bitmap = ConvertUtils.view2Bitmap(view);
Drawable drawable = ConvertUtils.bitmap2Drawable(bitmap);
tempTaskList.add(createDownaloadTask(new DownloadTask(0, drawable)));
stringBuilder.insert(j, " ");
j = j + 1;
view.destroyDrawingCache();
} List<String> tagPathList = getProductDelivery(skuDelivery);
if (tagPathList != null && tagPathList.size() > 0) {
for (int i = 0; i < tagPathList.size(); i++) {
if (TextUtils.isEmpty(tagPathList.get(i))) {
continue;
}
tempTaskList.add(createDownaloadTask(new DownloadTask(i + 1, tagPathList.get(i))));
stringBuilder.insert(j, " ");
}
} if (tempTaskList.size() <= 0) {
return;
}
// 合并任务
Observable.mergeDelayError(tempTaskList)
.subscribeOn(Schedulers.newThread())
.unsubscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ResultTask>() { Disposable mD;
List<ResultTask> temp = new ArrayList<>(); @Override
public void onSubscribe(Disposable d) {
mD = d;
} @Override
public void onNext(ResultTask resultTask) {
temp.add(resultTask);
} @Override
public void onError(Throwable e) { } @Override
public void onComplete() {
if (mD != null) {
mD.dispose();
} // 排序
Collections.sort(temp, new Comparator<ResultTask>() {
@Override
public int compare(ResultTask o1, ResultTask o2) {
return o1.position - o2.position;
}
}); // 开始绘制
SpannableStringBuilder sb = new SpannableStringBuilder();
sb.append(stringBuilder.toString());
for (int i = 0; i < temp.size(); i++) {
ResultTask task = temp.get(i);
float dpValue = 24;
if (!TextUtils.isEmpty(tag) && i == 0) {
dpValue = 16;
}
float radio = (float) SizeUtils.dp2px(dpValue) / task.drawable.getIntrinsicHeight();
task.drawable.setBounds(0, 0, (int) (task.drawable.getIntrinsicWidth() * radio), SizeUtils.dp2px(dpValue));
CenterAlignImageSpan imageSpan = new CenterAlignImageSpan(task.drawable);
sb.setSpan(imageSpan, i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
textView.setText(sb);
}
}); } // 下载任务类
private static class DownloadTask {
private int position;
private String imgUrl;
private int width;
private int height;
private Drawable drawable; public DownloadTask(int position, String imgUrl) {
this.position = position;
this.imgUrl = imgUrl;
} public DownloadTask(int position, Drawable drawable) {
this.position = position;
this.drawable = drawable;
}
} // 承载任务的类
private static class ResultTask {
private int position;
private Drawable drawable;
private int width;
private int height;
} /**
* 转化标签
*/
private List<String> getProductDelivery(List<SkuDeliveryBean> skuDelivery) {
List<String> temp = new ArrayList<>();
if (skuDelivery != null) {
for (SkuDeliveryBean bean : skuDelivery) {
if (bean == null) {
continue;
}
temp.add(bean.getSkuDeliveryUrl());
}
}
return temp;
}
}

ImageSpan

public class CenterAlignImageSpan extends ImageSpan {

    public CenterAlignImageSpan(Drawable drawable) {
super(drawable);
} @Override
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
Drawable d = getDrawable();
Rect rect = d.getBounds();
if (fm != null) {
Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
int fontHeight = fmPaint.bottom - fmPaint.top;
int drHeight = rect.bottom - rect.top; int top = drHeight / 2 - fontHeight / 4;
int bottom = drHeight / 2 + fontHeight / 4; fm.ascent = -bottom;
fm.top = -bottom;
fm.bottom = top;
fm.descent = top;
}
return rect.right;
} @Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
Drawable b = getDrawable();
canvas.save();
int transY = 0;
transY = ((bottom - top) - b.getBounds().bottom) / 2 + top;
canvas.translate(x, transY);
b.draw(canvas);
canvas.restore();
} }

Android-textview图文混排(网络图片)的更多相关文章

  1. TextView图文混排

    大家都知道,textView有一个setCompoundDrawables的方法来设置上下左右位置的图标,当然,也可以在xml布局文件中设置,然而问题来了,假如我们把图标放在左边,当我们让TextVi ...

  2. TextView + Spanned实现图文混排以及图片点击交互

    最近要实现图文混排的需求,webview过大,所以想到了用SpannableStringBuilder来实现. 不过参考了大量国内文章,大多数是教你如何实现图文混排,并没有提及图片点击交互的.有翻阅了 ...

  3. Android TextView图文混合编排

    Android TextView图文混合编排 实现技术细节不难,两个要点:1.html代码的混合编写.2,重写ImageGetter.例如:布局: <?xml version="1.0 ...

  4. Android 自绘TextView解决提前换行问题,支持图文混排

    先看下效果图: 上面是MTextView,下面是默认的TextView. 一.原因 用最简单的全英文句子为例,如果有一个很长的单词,这一行剩余的空间显示不下了,那么规则就是不打断单词,而是把整个单词丢 ...

  5. Android TextView中图文混排设置行间距导致高度不一致问题解决

    最近项目中需要实现一个评论带表情的功能,刚开始一切顺利,非常easy,突然有一天发现文字跟表情混排的时候,TextView中图文高度不一致,excuse...什么鬼,之前明明测试过图文混排,不存在这个 ...

  6. Android中Textview显示Html,图文混排,支持图片点击放大

    本文首发于网易云社区 对于呈现Html文本来说,Android提供的Webview控件可以得到很好的效果,但使用Webview控件的弊端是效率相对比较低,对于呈现简单的html文本的话,杀鸡不必使用牛 ...

  7. android:怎样在TextView实现图文混排

    我们通常在TextView文本中设置文字.但是怎样设置图文混排呢? 我就在这里写一个样例 .我们须要用到一点简单的HTML知识 在TextView中预订了一些类似HTML的标签,通过标签能够使Text ...

  8. 使用android SpannableStringBuilder实现图文混排

    项目开发中需要实现这种效果 多余两行,两行最后是省略号,省略号后面是下拉更多 之前用过的是Html.fromHtml去处理图文混排的,仅仅是文字后图片或者文字颜色字体什么的, 但是这里需要在最后文字的 ...

  9. 使用android SpannableStringBuilder实现图文混排,看到许多其他

    项目开发需要达到这种效果 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmFuY3lsb3ZlamF2YQ==/font/5a6L5L2T/fontsiz ...

  10. Android自动解析html带图片,实现图文混排

    在android中,如何将html代码转换为text,然后显示在textview中呢,有一个简单直接的方法: textView.setText(Html.fromHtml(content)); 然而用 ...

随机推荐

  1. sql server 性能调优之 资源等待PAGELATCH

    一.概述 在前几章介绍过 sql server 性能调优资源等待之PAGEIOLATCH,PAGEIOLATCH是出现在sql server要和磁盘作交互的时候,所以加个IO两个字.这次来介绍PAGE ...

  2. 2012-2014 三年浙江 acm 省赛 题目 分类

    The 9th Zhejiang Provincial Collegiate Programming Contest A    Taxi Fare    25.57% (166/649)     (水 ...

  3. Linux命令行文本工具

    浏览文件 cat 查看文件内容 more 以翻页形式查看文件内容(只能向下翻页) less 以翻页形式查看文件内容(可以上下翻页) head 查看文件的头几行(默认10行) tail 查看文件的尾几行 ...

  4. Ubuntu 18.04.1 搭建Java环境和HelloWorld

    一.搭建Java环境 系统环境 Ubuntu 18.04.1 JDK 8 IDEA 2018.2 1.下载JDK 官网地址:http://www.oracle.com/technetwork/java ...

  5. 痞子衡嵌入式:SEGGER J-Link仿真器硬件版本变迁

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是J-Link仿真器版本变迁. 硬件版本 主控芯片 固件升级工具 V7 ARM7TDMI, 55MHz Atmel AT91SAM7S64 ...

  6. Haskell复习笔记(一)

    Haskell笔记这是第三次总结,前两次都因为各种原因丢失了,对于Haskell我算不上什么大神,只不过在大学时为了学习算法时选择了Haskell. 当时的入门书籍选择的是<Learn You ...

  7. TensorFlow(2)Softmax Regression

    Softmax Regression Chapter Basics generate random Tensors Three usual activation function in Neural ...

  8. “笨方法”学习Python笔记(1)-Windows下的准备

    Python入门书籍 来自于开源中国微信公众号推荐的一篇文章 全民Python时代,豆瓣高级工程师告诉你 Python 怎么学 问:请问你目前最好的入门书是那本?有没有和PHP或者其他语言对比讲Pyt ...

  9. tomcat和jdk版本兼容(Tomcat版本要比jdk高)

    用的tomcat是低版本的,但是用的jdk却是高版本的,用Servlet做的项目运行都没有问题,但是直接运行jsp却死活都运行失败. 最后发现是tomcat和jdk的版本问题造成的. 总结如下: to ...

  10. 解决org.hibernate.HibernateException: identifier of an instance of com.ahd.entity.Order was altered from2 to 0

    错误信息 严重: Servlet.service() for servlet [springmvc] in context with path [/order] threw exception [Re ...