现在在做一个题库类的项目,由于有些数学符号或者化学符号之类的没办法直接在前端显示,所以就使用了图文混排;
后台返回的数据直接是HTML格式的数据。
所以就开始去研究控件如何去显示HTML
先贴上参考的文章,感谢分享!
1、这种只适合加载本地图片,或者兼容版本在4.0以下
Android中Textview显示带html文本二-------【Textview显示本地图片】
上面这种方式,只要在百度上搜一下 Android TextView 设置 HTML 数据,就会找出来很多类似的,但是感觉这为大神写的最好!
如果HTML数据中,只有文本的话,使用下面的写法就Ok了,
//如果 HTML数据中没有图片,仅仅是文本的话,直接这样设置就好了 String html = "<p>这个就是测试</p><span>数据</span><img src=\"http://as114.com/pic/logo.png\" />"; TextView mTvHello = (TextView) this.findViewById(R.id.tv_hello); mTvHello.setText(Html.fromHtml(html));
如果HTML数据中包含本地图片路径,你可以参考上面链接里,这位大神些的两种方式就可以了
//主要是多了这个加载图片的参数 Html.ImageGetter imageGetter = new Html.ImageGetter() { @Override public Drawable getDrawable(String source) { //实现方式可以参考上面的帖子,根据自己的需求来实现 return null; } }; //Html。fromHtml时 加上上面的参数 mTvHello.setText(Html.fromHtml(html,imageGetter,null));
其实如果你的项目只兼容到 4.0以下,并且不怕卡的话,上面的帖子里也有实现方式(但是这种需求估计现在没有!)
说一下原因,4.0以下是可以再主线程请求网络的,但是4.0以后是不可以在主线程请求网络,
url = new URL(source); drawable = Drawable.createFromStream(url.openStream(), "");
上面这种写法就要在主线程加载图片, 虽然4.0以下可以使用,但是如果图片大的话,估计就直接卡死了,所以还是不要用了!
如果是本地图片的话,可以使用帖子中的两种图片方式,根据自己的需求来实现就OK了;
2、异步加载HTML中的图片 参考文章(stackoverflow 上的,有时候可以能访问不了,自己找办法……)
Android HTML ImageGetter as AsyncTask
上面的帖子完美解决了问题!
贴出代码,省的某些朋友不能访问帖子,看不了代码
import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; /** * Created by Administrator on 2015/4/30. */ public class URLDrawable extends BitmapDrawable{ // the drawable that you need to set, you could set the initial drawing // with the loading image if you need to protected Drawable drawable; @Override public void draw(Canvas canvas) { // override the draw to facilitate refresh function later if(drawable != null) { drawable.draw(canvas); } } }
package com.jddl.tvhtmldemo; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.text.Html; import android.view.View; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; /** * Created by Administrator on 2015/4/30. */ public class URLImageParser implements Html.ImageGetter { Context c; View container; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } /** * Construct the URLImageParser which will execute AsyncTask and refresh the container * * @param t * @param c */ public URLImageParser(View t, Context c) { this.c = c; this.container = t; } public Drawable getDrawable(String source) { URLDrawable urlDrawable = new URLDrawable(); // get the actual source ImageGetterAsyncTask asyncTask = new ImageGetterAsyncTask(urlDrawable); asyncTask.execute(source); // return reference to URLDrawable where I will change with actual image from // the src tag return urlDrawable; } public class ImageGetterAsyncTask extends AsyncTask<String, Void, Drawable> { URLDrawable urlDrawable; public ImageGetterAsyncTask(URLDrawable d) { this.urlDrawable = d; } @Override protected Drawable doInBackground(String... params) { String source = params[0]; return fetchDrawable(source); } @Override protected void onPostExecute(Drawable result) { // set the correct bound according to the result from HTTP call urlDrawable.setBounds(0, 0, result.getIntrinsicWidth(), result.getIntrinsicHeight()); // change the reference of the current drawable to the result // from the HTTP call urlDrawable.drawable = result; // redraw the image by invalidating the container URLImageParser.this.container.invalidate(); } /** * Get the Drawable from URL * * @param urlString * @return */ public Drawable fetchDrawable(String urlString) { try { InputStream is = fetch(urlString); Drawable drawable = Drawable.createFromStream(is, "src"); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); return drawable; } catch (Exception e) { return null; } } private InputStream fetch(String urlString) throws MalformedURLException, IOException { DefaultHttpClient httpClient = new DefaultHttpClient(); HttpGet request = new HttpGet(urlString); HttpResponse response = httpClient.execute(request); return response.getEntity().getContent(); } } public URLImageParser() { super(); } }
由于我的项目中有选择题,和单选题,所以我用到了 TextView , RadioButton 和 CheckBox 三种控件,
下面是使用时的代码
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView mTvHello = (TextView) this.findViewById(R.id.tv_hello); String html = "<p>这个就是测试</p><span>数据</span><img src=\"http://as114.com/pic/logo.png\" />"; mTvHello.setMovementMethod(ScrollingMovementMethod.getInstance()); URLImageParser urlImgGetter = new URLImageParser(mTvHello, this); mTvHello.setText(Html.fromHtml(html, urlImgGetter, null)); RadioButton mRbHtml = (RadioButton) this.findViewById(R.id.rb_html); URLImageParser urlImgGetterRb = new URLImageParser(mRbHtml, this); mRbHtml.setText(Html.fromHtml(html, urlImgGetterRb, null)); CheckBox mCbHtml = (CheckBox) this.findViewById(R.id.cb_html); URLImageParser urlImgGetterCb = new URLImageParser(mCbHtml, this); mRbHtml.setText(Html.fromHtml(html, urlImgGetterCb, null)); } }
简单说一下我的理解(小弟 从事Android 不长,如有理解错误还请大家多多指教!)
URLImageParser 类实现了 Html.ImageGetter 接口, 写法和别的没什么区别,
在getDrawable先返回一个urlDrawable,是一个空的图片
然后使用,异步加载图片,加载完成后在刷新图片和View
思路貌似很简单,但是之前没想着怎么实现!
再次感谢分享!
因为大多数都是写的TextView 使用的方法,
但是我想: 因为RadioButton 和 Checkbox 都是 TextView 的子类,所以应该也可以使用!
最终测试证明的想法是可行的,贴上 运行照片