工作太忙,不做过多的解释了,核心是用到了 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(); } }