前几天在做一个Gradle用户指南的应用程序,使用的是TextView来加载HTML内容(至于为什么不用WebView,我也没有认真使用并比较过,也许以后会换吧),其中遇见了一些纠结的问题,所幸主要的问题都一一解决了。
下面说一下遇见的几个问题及我的解决方法。
在TextView中加载HTML图片,需要实现Html.ImageGetter接口,然后在public Drawable getDrawable(String source)中去获取图片。图片获取我是直接使用了ImageLoader,一来加载图片省事,二来带缓存功能,正是我想要的。但是getDrawable方法是在主线程中调用的,且要求返回Drawable对象用于显示,而我们是不能在主线程中进行网络访问的,所以需要异步加载。ImageLoader本身已经有异步加载的功能,所以我们需要将它与getDrawable方法结合起来。这里用的方法与百度上常见到的方法略有不同,因为百度上的方法在我这里会有BUG,在第二次进入时图片经常加载不出来。
首先,写一个类继承BitmapDrawable,代码如下:
package com.githang.gradledoc.chapter; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; /** * User: Geek_Soledad([email protected]) * Date: 2014-11-30 * Time: 00:09 * FIXME */ public class URLDrawable extends BitmapDrawable { protected Bitmap bitmap; @Override public void draw(Canvas canvas) { if (bitmap != null) { canvas.drawBitmap(bitmap, 0, 0, getPaint()); } } }
然后写一个类实现Html.ImageGetter接口,代码如下:
public class URLImageParser implements Html.ImageGetter { TextView mTextView; public URLImageParser(TextView textView) { this.mTextView = textView; } @Override public Drawable getDrawable(String source) { final URLDrawable urlDrawable = new URLDrawable(); Log.d("ChapterActivity", Consts.BASE_URL + source); ImageLoader.getInstance().loadImage(Consts.BASE_URL + source, new SimpleImageLoadingListener() { @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { urlDrawable.bitmap = loadedImage; urlDrawable.setBounds(0, 0, loadedImage.getWidth(), loadedImage.getHeight()); mTextView.invalidate(); mTextView.setText(mTextView.getText()); // 解决图文重叠 } }); return urlDrawable; } }这里的mTextView是我们要加载图片的TextView对象。这里我暂未对图片做自适应屏幕的适配,做的比较简单,只是把加载后的图片设置到之前返回的URLDrawable对象中的urlDrawable去,然后调用mTextView.invalidate()方法更新界面。
但是这样写完之后,还有一个问题。尽管我们对urlDrawable调用了setBounds设置它的边框,但是还是会出现图片重叠的问题。需要重新设置一下mTextView的内容,如上面代码中的:
mTextView.setText(mTextView.getText());
设置HTML到TextView的代码如下:
mDocView.setText(Html.fromHtml(doc, new URLImageParser(mDocView), null));
/** * 处理代码显示问题. * * @param chapter 章节内容的html元素。 */ private void handlerPreTag(Element chapter) { Elements preElems = chapter.select("pre"); for (Element elem : preElems) { elem.html(elem.html().replaceAll("\n", "<br/>").replaceAll(" ", " ")); } }