Android-textview图文混排(网络图片)
工作太忙,不做过多的解释了,核心是用到了 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图文混排(网络图片)的更多相关文章
- TextView图文混排
大家都知道,textView有一个setCompoundDrawables的方法来设置上下左右位置的图标,当然,也可以在xml布局文件中设置,然而问题来了,假如我们把图标放在左边,当我们让TextVi ...
- TextView + Spanned实现图文混排以及图片点击交互
最近要实现图文混排的需求,webview过大,所以想到了用SpannableStringBuilder来实现. 不过参考了大量国内文章,大多数是教你如何实现图文混排,并没有提及图片点击交互的.有翻阅了 ...
- Android TextView图文混合编排
Android TextView图文混合编排 实现技术细节不难,两个要点:1.html代码的混合编写.2,重写ImageGetter.例如:布局: <?xml version="1.0 ...
- Android 自绘TextView解决提前换行问题,支持图文混排
先看下效果图: 上面是MTextView,下面是默认的TextView. 一.原因 用最简单的全英文句子为例,如果有一个很长的单词,这一行剩余的空间显示不下了,那么规则就是不打断单词,而是把整个单词丢 ...
- Android TextView中图文混排设置行间距导致高度不一致问题解决
最近项目中需要实现一个评论带表情的功能,刚开始一切顺利,非常easy,突然有一天发现文字跟表情混排的时候,TextView中图文高度不一致,excuse...什么鬼,之前明明测试过图文混排,不存在这个 ...
- Android中Textview显示Html,图文混排,支持图片点击放大
本文首发于网易云社区 对于呈现Html文本来说,Android提供的Webview控件可以得到很好的效果,但使用Webview控件的弊端是效率相对比较低,对于呈现简单的html文本的话,杀鸡不必使用牛 ...
- android:怎样在TextView实现图文混排
我们通常在TextView文本中设置文字.但是怎样设置图文混排呢? 我就在这里写一个样例 .我们须要用到一点简单的HTML知识 在TextView中预订了一些类似HTML的标签,通过标签能够使Text ...
- 使用android SpannableStringBuilder实现图文混排
项目开发中需要实现这种效果 多余两行,两行最后是省略号,省略号后面是下拉更多 之前用过的是Html.fromHtml去处理图文混排的,仅仅是文字后图片或者文字颜色字体什么的, 但是这里需要在最后文字的 ...
- 使用android SpannableStringBuilder实现图文混排,看到许多其他
项目开发需要达到这种效果 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmFuY3lsb3ZlamF2YQ==/font/5a6L5L2T/fontsiz ...
- Android自动解析html带图片,实现图文混排
在android中,如何将html代码转换为text,然后显示在textview中呢,有一个简单直接的方法: textView.setText(Html.fromHtml(content)); 然而用 ...
随机推荐
- 多线程的音频打标记的python实现(原创)
技术难度: ①需要一个UI界面,并且其中可进行相关参数的自调,最开始使用的是pygame的框架,后来转用tk界面: ②需要可以播放音频文件,MP3.WMA等格式: ③需要在播放音频的同时进行打标签操作 ...
- visual Studio 2017 扩展开发(三)《绑定快捷键到菜单项》
如何将键盘快捷方式映射到自定义按钮,怎么使用快捷键启动自己创建的菜单,刚开始做的时候迷糊了,找了很久.可能也是因为刚开始做不是很明白,后面慢慢就懂了.其实非常简单的. 很多快捷键已经在Visual s ...
- mysql 开发进阶篇系列 7 锁问题(innodb锁争用情况及锁模式)
1 .获取innodb行锁争用情况 1.1 通过检查innodb_row_lock状态变量来分析系统上的行锁的争夺情况 SHOW STATUS LIKE 'innodb_row_lock%' 通过in ...
- 【Objective-C】内存管理
涉及三大知识点:引用计数器,属性参数,自动释放池 一.引用计数器(程序编译时Xcode可以自动给你的代码添加内存释放代码,如果编写手动释放代码Xcode会报错) 1.关闭ARC(xcode 4.x之后 ...
- Java后端工程师必备书单(含大后端方向相关书籍)
学习Java和其他技术的资源其实非常多,但是我们需要取其精华去其糟粕,选择那些最好的,最适合我们的,同时也要由浅入深,先易后难.基于这样的一个标准,我在这里为大家提供一份Java的学习资源清单. 一: ...
- Java 代理模式
熟悉设计模式的人对于代理模式可能都不陌生.那什么事代理呢,例如我们要买一件国外的商品,但是自己买不到只能去找代购,这个代购就是我们的代理.我们来了解下java中的代理 静态代理 我们来举一个开车的例子 ...
- ES6躬行记(8)——数字
一.进制 ES6不仅完善了数字的八进制形式,还补充了一种十六进制形式,并且添加了全新的二进制形式.下面的三个变量分别表示八进制.十六进制和二进制的10,注释中给出了该进制的另一种写法. var oct ...
- 基于redis的分布式锁实现
1.分布式锁介绍 在计算机系统中,锁作为一种控制并发的机制无处不在. 单机环境下,操作系统能够在进程或线程之间通过本地的锁来控制并发程序的行为.而在如今的大型复杂系统中,通常采用的是分布式架构提供服务 ...
- mysql+mycat实现读写分离
centos7 master slave mycat1.6 client 192.168.41.10 192.168.41.11 192.168.41.12 192.168.41.13 实 ...
- openssl基本原理 + 生成证书 + 使用实例
前期准备 : 安装xampp:打开文件E:\xampp\apache\bin\openssl.exe 右键 以管理员身份运行 ------转载自 https://blog.csdn.net/oldm ...