博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Picasso解决 TextView加载html图片异步显示
阅读量:4879 次
发布时间:2019-06-11

本文共 12890 字,大约阅读时间需要 42 分钟。

项目中有这样一个需求:

  textview加载一段 html标签 其中包含 "<Img url= " 图片异步展示 而且 根据图片的比例 宽度满屏展示。

思路:

  重写textview Html.fromHtml方法  以及 图片Picasso展示(后面会附带Picasso 的两个转换类)

感觉网上没有合适的或者用的是Gilde加载 其实无论是Gilde还是Picasso加载豆豆都能满足我们的需求。

 

需求描述完毕 上张帅图:

  

好吧 废话不多说了 直接上实现代码 

     RichText:  

public class RichText extends TextView {
private Drawable placeHolder, errorImage;//占位图,错误图 private OnImageClickListener onImageClickListener;//图片点击回调 private HashSet
targets; private int d_w = 500; private int d_h = 500; public RichText(Context context) {
this(context, null); } public RichText(Context context, AttributeSet attrs) {
this(context, attrs, 0); } public RichText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) {
targets = new HashSet<>(); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RichText); placeHolder = typedArray.getDrawable(R.styleable.RichText_placeHolder); errorImage = typedArray.getDrawable(R.styleable.RichText_errorImage); d_w = typedArray.getDimensionPixelSize(R.styleable.RichText_default_width, d_w); d_h = typedArray.getDimensionPixelSize(R.styleable.RichText_default_height, d_h); if (placeHolder == null) {
placeHolder = new ColorDrawable(Color.GRAY); } placeHolder.setBounds(0, 0, d_w, d_h); if (errorImage == null) {
errorImage = new ColorDrawable(Color.GRAY); } errorImage.setBounds(0, 0, d_w, d_h); typedArray.recycle(); } /** * 设置富文本 * * @param text 富文本 */ public void setRichText(String text) {
targets.clear(); Spanned spanned = Html.fromHtml(text, asyncImageGetter, null); SpannableStringBuilder spannableStringBuilder; if (spanned instanceof SpannableStringBuilder) {
spannableStringBuilder = (SpannableStringBuilder) spanned; } else {
spannableStringBuilder = new SpannableStringBuilder(spanned); } ImageSpan[] imageSpans = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), ImageSpan.class); final List
imageUrls = new ArrayList<>(); for (int i = 0, size = imageSpans.length; i < size; i++) {
ImageSpan imageSpan = imageSpans[i]; String imageUrl = imageSpan.getSource(); int start = spannableStringBuilder.getSpanStart(imageSpan); int end = spannableStringBuilder.getSpanEnd(imageSpan); imageUrls.add(imageUrl); final int finalI = i; ClickableSpan clickableSpan = new ClickableSpan() {
@Override public void onClick(View widget) {
if (onImageClickListener != null) {
onImageClickListener.imageClicked(imageUrls, finalI); } } }; ClickableSpan[] clickableSpans = spannableStringBuilder.getSpans(start, end, ClickableSpan.class); if (clickableSpans != null && clickableSpans.length != 0) {
for (ClickableSpan cs : clickableSpans) {
spannableStringBuilder.removeSpan(cs); } } spannableStringBuilder.setSpan(clickableSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } super.setText(spanned); setMovementMethod(LinkMovementMethod.getInstance()); } private void addTarget(Target target) {
targets.add(target); } /** * 异步加载图片(依赖于Picasso) */ private Html.ImageGetter asyncImageGetter = new Html.ImageGetter() {
@Override public Drawable getDrawable(String source) {
final URLDrawable urlDrawable = new URLDrawable(); Target target = new Target() {
@Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
Drawable drawable = new BitmapDrawable(getContext().getResources(), bitmap); drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight()); urlDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight()); urlDrawable.setDrawable(drawable); RichText.this.setText(getText()); } @Override public void onBitmapFailed(Drawable errorDrawable) {
// urlDrawable.setBounds(errorDrawable.getBounds()); urlDrawable.setDrawable(errorDrawable); } @Override public void onPrepareLoad(Drawable placeHolderDrawable) {
// urlDrawable.setBounds(placeHolderDrawable.getBounds()); urlDrawable.setDrawable(placeHolderDrawable); } }; addTarget(target); Picasso.with(getContext()).load(source).transform(new ImageTransform()).into(target);//.placeholder(placeHolder).error(errorImage) return urlDrawable; } }; private static final class URLDrawable extends BitmapDrawable {
private Drawable drawable; @SuppressWarnings("deprecation") public URLDrawable() {
} @Override public void draw(Canvas canvas) {
if (drawable != null) drawable.draw(canvas); } public void setDrawable(Drawable drawable) {
this.drawable = drawable; } } public void setPlaceHolder(Drawable placeHolder) {
this.placeHolder = placeHolder; this.placeHolder.setBounds(0, 0, d_w, d_h); } public void setErrorImage(Drawable errorImage) {
this.errorImage = errorImage; this.errorImage.setBounds(0, 0, d_w, d_h); } public void setOnImageClickListener(OnImageClickListener onImageClickListener) {
this.onImageClickListener = onImageClickListener; } public interface OnImageClickListener {
/** * 图片被点击后的回调方法 * * @param imageUrls 本篇富文本内容里的全部图片 * @param position 点击处图片在imageUrls中的位置 */ void imageClicked(List
imageUrls, int position); } } // ============================ImageTransform 处理图片比例展示
public class ImageTransform implements Transformation {
private String Key = "ImageTransform"; @Override public Bitmap transform(Bitmap source) {//40 是我项目中 的图片间距 int targetWidth = ScreenUtil.getScreenWidth(App.getContext()) - DisplayUtil.dp2px(App.getContext(), 40); if (source.getWidth() == 0) {
return source; } //如果图片小于设置的宽度,做处理 if (source.getWidth() < targetWidth) {
double aspectRatio = (double) source.getHeight() / (double) source.getWidth(); int targetHeight = (int) (targetWidth * aspectRatio); if (targetHeight != 0 && targetWidth != 0) {
Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false); if (result != source) {
// Same bitmap is returned if sizes are the same source.recycle(); } return result; } else {
return source; } } else {
return source; } } @Override public String key() {
return Key; } } //=========================其中 40是我项目左右两边的间距 配置
/**  * 获取屏幕的宽度px  */ public static int getScreenWidth(Context context) {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸 windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高 return outMetrics.widthPixels; }
public static int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } //最后使用
RichText.setRichText();就行 //=============================================================================扩展 Picasso加载圆形图片 解决比例失真问题 可不看
/**  * 毕加索 设置圆形头像  * Created by swplzj on 16/12/10.  */ public class CircleTransform implements Transformation {
private String Key = "CircleTransform"; private Context mContext; private int h = 60; public CircleTransform(Context context) {
this.mContext = context; } public CircleTransform(Context context,int height) {
this.mContext = context; this.h = height; } @Override public Bitmap transform(Bitmap source) {// 60 是我图片头像的宽高度 压缩 Bitmap zoomBitmp = BitmapUtils.zoom(source, DisplayUtil.dp2px(mContext, h), DisplayUtil.dp2px(mContext, h)); Bitmap bitmap = BitmapUtils.circleBitmap(zoomBitmp); source.recycle(); return bitmap;//返回圆形的Bitmap对象 } /** * 该方法没有什么实际意义,但是要保证其返回的值不能为null! * @return */ @Override public String key() {
return Key; } }
public class BitmapUtils {
/**将矩形的Bitmap对象转换为圆形的Bitmap * @param source:待处理的 矩形的Bitmap * @return :需返回的圆形的Bitmap */ public static Bitmap circleBitmap(Bitmap source){
//获取Bitmap的宽度 int width = source.getWidth(); //返回一个正方形的Bitmap对象 Bitmap bitmap = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888); //提供指定宽高的canvas Canvas canvas = new Canvas(bitmap); //提供画笔 Paint paint = new Paint(); paint.setAntiAlias(true); //背景:在画布上绘制一个圆 canvas.drawCircle(width / 2, width / 2, width / 2, paint); //设置图片相交情况下的处理方式 //setXfermode:设置当绘制的图像出现相交情况时候的处理方式的,它包含的常用模式有哪几种 //PorterDuff.Mode.SRC_IN 取两层图像交集部门,只显示上层图像,注意这里是指取相交叉的部分,然后显示上层图像 //PorterDuff.Mode.DST_IN 取两层图像交集部门,只显示下层图像 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); //前景:在画布上绘制一个bitmap canvas.drawBitmap(source, 0, 0, paint); return bitmap; } /**对bitmap进行压缩处理 * @param source :需要被处理的Bitmap * @param width 需要压缩成的宽度 必须为浮点型 * @param height 需要压缩成的高度 必须为浮点型 * @return 返回压缩后的Bitmap * 注意!必须提供参数2,3为浮点型。 */ public static Bitmap zoom(Bitmap source,float width,float height){
Matrix matrix = new Matrix(); float scaleX = width / source.getWidth(); float scaleY = height / source.getHeight(); matrix.postScale(scaleX, scaleY); Bitmap bitmap = Bitmap.createBitmap(source,0,0,source.getWidth(),source.getHeight(),matrix,true); return bitmap; } } 遗漏或者不清楚的可以联系我QQ群:521039620 Android&Go,Let's go! 感谢作者 https://github.com/zzhoujay/RichText (Gilde方式实现) 以及没提到的网上参考 谢谢大家。 ==================2017年4月26号 更新========================== RichText 加载多张图片 或者图片超出屏幕处理
private Html.ImageGetter asyncImageGetter = new Html.ImageGetter() {
@Override public Drawable getDrawable(String source) {
final URLDrawable urlDrawable = new URLDrawable(); Target target = new Target() {
@Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
int screenWidth = ScreenUtil.getScreenWidth(App.getContext());// 获取屏幕宽度 screenWidth = screenWidth- DisplayUtil.dp2px(App.getContext(),40);// 这个是我项目中 左右距离20dp int height = bitmap.getHeight() * screenWidth / bitmap.getWidth(); Bitmap result = Bitmap.createScaledBitmap(bitmap, screenWidth, height, true);//等比压缩 设置 true 3M 压缩到200多K 关于清晰度 你回头可以自己调 优化 Drawable drawable = new BitmapDrawable(getContext().getResources(), result); drawable.setBounds(0, 0, result.getWidth(), result.getHeight()); urlDrawable.setBounds(0, 0, result.getWidth(), result.getHeight()); urlDrawable.setDrawable(drawable); RichText.this.setText(getText()); } @Override public void onBitmapFailed(Drawable errorDrawable) {
urlDrawable.setDrawable(errorDrawable); } @Override public void onPrepareLoad(Drawable placeHolderDrawable) {
urlDrawable.setDrawable(placeHolderDrawable); } }; addTarget(target); Picasso.with(getContext()).load(source).transform(new ImageTransform()).into(target);//.placeholder(placeHolder).error(errorImage) return urlDrawable; } };

==== ps 关于三星手机 只能成功加载一张图片 还在解决中ing 

 

转载于:https://www.cnblogs.com/yizuochengchi2012/p/6289126.html

你可能感兴趣的文章
Git闪退问题
查看>>
Linux命令
查看>>
Android UI线程和非UI线程
查看>>
SpringBoot定时任务
查看>>
获取磁盘空间
查看>>
HTML5 是什么
查看>>
Xamarin Android项目提示SDK版本太老
查看>>
用信号量进程同步与互斥
查看>>
java容器简要概述
查看>>
Xdebug断点调试的工作原理详解
查看>>
CentOS7+Nginx设置Systemctl restart nginx.service服务
查看>>
web服务器,验证码,Xftp使用方法
查看>>
割点 - 模板
查看>>
使用maven 如何生成源代码的jar包
查看>>
Ubuntu 16.04.6 + Win10 双系统时间错误且不一致
查看>>
协同过滤代码---loadMovieLens.py文件
查看>>
条件分布
查看>>
Python之字符串的特性及常用方法
查看>>
第三次作业——结对编程
查看>>
ora-12899解决方法
查看>>