标签:
由于应用中的数据大量采用富文本排版 所以需要客户端解析格式去显示
虽然WebView 可以做到 可是其中的图片下载并没有没有通过我们自己的缓存机制
在git上找到了一个基于picasso的RichText
替换成我们所使用的Fresco 运行起来 没有问题 比起WebView也要流畅很多
所以分享一下实现的代码 有问题 互相帮助改进
现存问题:不支持gif格式
talk is cheap show me the code
/** * Created by sunche on 15/11/10. coffee in code out! */ public class RichText extends TextView { private Drawable placeHolder, errorImage;//占位图,错误图 private OnImageClickListener onImageClickListener;//图片点击回调 MultiDraweeHolder<GenericDraweeHierarchy> mMultiDraweeHolder; private int d_w = 200; private int d_h = 200; public RichText(Context context) { this(context, null); init(context, null); } public RichText(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context, attrs); } public RichText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) { 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(); initDraweeHolder(); } private void initDraweeHolder() { mMultiDraweeHolder = new MultiDraweeHolder<>(); } /** * 设置富文本 * * @param text 富文本 */ public void setRichText(String text) { 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<String> 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()); } /** * 异步加载图片(依赖于fresco) */ private Html.ImageGetter asyncImageGetter = new Html.ImageGetter() { @Override public Drawable getDrawable(String source) { Log.i("RichText", "asyncImageGetter getDrawable.source:" + source); final URLDrawable urlDrawable = new URLDrawable(); GenericDraweeHierarchy mHierarchy = new GenericDraweeHierarchyBuilder(getResources()) .build(); final DraweeHolder draweeHolder = new DraweeHolder<GenericDraweeHierarchy>(mHierarchy); mMultiDraweeHolder.add(draweeHolder); DraweeController controller = Fresco.newDraweeControllerBuilder() .setUri(Uri.parse(source)) .setOldController(draweeHolder.getController()) .setControllerListener(new ControllerListener<ImageInfo>() { @Override public void onSubmit(String id, Object callerContext) { urlDrawable.setBounds(placeHolder.getBounds()); urlDrawable.setDrawable(placeHolder); RichText.this.setText(getText()); } @Override public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable animatable) { final Drawable drawable = draweeHolder.getHierarchy().getTopLevelDrawable(); drawable.setBounds(0, 0, imageInfo.getWidth(), imageInfo.getHeight()); urlDrawable.setBounds(0, 0, imageInfo.getWidth(), imageInfo.getHeight()); urlDrawable.setDrawable(drawable); RichText.this.setText(getText()); Log.i("RichText", "onFinalImageSet width:" + imageInfo.getWidth() + ",height:" + imageInfo.getHeight()); } @Override public void onIntermediateImageSet(String id, ImageInfo imageInfo) { Log.i("RichText", "onIntermediateImageSet width:" + imageInfo.getWidth() + ",height:" + imageInfo.getHeight()); } @Override public void onIntermediateImageFailed(String id, Throwable throwable) { } @Override public void onFailure(String id, Throwable throwable) { urlDrawable.setBounds(errorImage.getBounds()); urlDrawable.setDrawable(errorImage); RichText.this.setText(getText()); } @Override public void onRelease(String id) { } }) .build(); draweeHolder.setController(controller); return urlDrawable; } }; @Override protected boolean verifyDrawable(Drawable who) { if (who instanceof URLDrawable && mMultiDraweeHolder.verifyDrawable(((URLDrawable) who).getDrawable())) { return true; } // 对其他Drawable的验证逻辑 return super.verifyDrawable(who); } 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 Drawable getDrawable() { return 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<String> imageUrls, int position); } @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); mMultiDraweeHolder.onDetach(); } @Override public void onStartTemporaryDetach() { super.onStartTemporaryDetach(); mMultiDraweeHolder.onDetach(); } @Override public void onAttachedToWindow() { super.onAttachedToWindow(); mMultiDraweeHolder.onAttach(); } @Override public void onFinishTemporaryDetach() { super.onFinishTemporaryDetach(); mMultiDraweeHolder.onAttach(); } }
<declare-styleable name="RichText"> <attr name="placeHolder" format="reference" /> <attr name="errorImage" format="reference" /> <attr name="default_width" format="dimension" /> <attr name="default_height" format="dimension" /> </declare-styleable>
标签:
原文地址:http://www.cnblogs.com/waterbear/p/4954817.html