Android 详解实现TextView加载带图片标签的Html并按比例缩放
2015-12-01 16:26
956 查看
最近在做商城类项目,有这样一个需求:商品详情里边有一个商品描述,这个字段最初设计的是用来显示一段描述文字,做完以后设计说需要支持图文的详情,没办法改吧~谁让咱是程序猿呢,很自然的就想到TextView加载Html标签,加载不带图片的Html片段很简单只要setText(Html.fromHtml(...))就可以了,仔细看了下源码
跟上边一个参数的方法差不多,重点是这一句Returns displayable styled text from the provided HTML string. Any <img> tags in the HTML will use the specified ImageGetter to request a representation of the image (use null if you don't want this) and the
specified TagHandler to handle unknown tags (specify null if you don't want this).大概意思是说任何<img>标签将使用指定的ImageGetter请求图像的表示,看完这个就感觉有点意思了,接着看
然而这是个虾米啊。。图片怎么辣么一丢丢,这特么怎么看,一万只草泥马在奔腾,接着改吧,既然小那就放大放大放大~~
刚才实现的ImageGetter里边不是有setBounds嘛,改一下宽高就行了,
宽取屏幕一半,高按原图比例缩放,到次才算大功告成,有什么不对的地方还请路过大神指导~
源码下载
/** * Returns displayable styled text from the provided HTML string. * Any <img> tags in the HTML will display as a generic * replacement image which your program can then go through and * replace with real images. * * <p>This uses TagSoup to handle real HTML, including all of the brokenness found in the wild. */ public static Spanned fromHtml(String source) { return fromHtml(source, null, null); }大概意思就是说此方法根据提供的Html返回一个带样式的字符串,然而所有的<img>标签将被显示成一个通用的图形,你可以在你的程序中替换为真正的图片,这不是扯呢吗?那是难倒服务器还单独把图片传过来?这显然不行啊,而且这个方法的实现是在
fromHtml(source, null, null);中,进去接着看
/** * Returns displayable styled text from the provided HTML string. * Any <img> tags in the HTML will use the specified ImageGetter * to request a representation of the image (use null if you don't * want this) and the specified TagHandler to handle unknown tags * (specify null if you don't want this). * * <p>This uses TagSoup to handle real HTML, including all of the brokenness found in the wild. */ public static Spanned fromHtml(String source, ImageGetter imageGetter, TagHandler tagHandler) { Parser parser = new Parser(); try { parser.setProperty(Parser.schemaProperty, HtmlParser.schema); } catch (org.xml.sax.SAXNotRecognizedException e) { // Should not happen. throw new RuntimeException(e); } catch (org.xml.sax.SAXNotSupportedException e) { // Should not happen. throw new RuntimeException(e); } HtmlToSpannedConverter converter = new HtmlToSpannedConverter(source, imageGetter, tagHandler, parser); return converter.convert(); }
跟上边一个参数的方法差不多,重点是这一句Returns displayable styled text from the provided HTML string. Any <img> tags in the HTML will use the specified ImageGetter to request a representation of the image (use null if you don't want this) and the
specified TagHandler to handle unknown tags (specify null if you don't want this).大概意思是说任何<img>标签将使用指定的ImageGetter请求图像的表示,看完这个就感觉有点意思了,接着看
/** * Retrieves images for HTML <img> tags. */ public static interface ImageGetter { /** * This methos is called when the HTML parser encounters an * <img> tag. The <code>source</code> argument is the * string from the "src" attribute; the return value should be * a Drawable representation of the image or <code>null</code> * for a generic replacement image. Make sure you call * setBounds() on your Drawable if it doesn't already have * its bounds set. */ public Drawable getDrawable(String source); }这是一个接口,需要我们自己实现,接口里边的方法是当HTML解释遇到 <img>标签时候会调用,参数source就是<img>中的src,也就是图片的路径了,好了到这里已经有点眉目了,前边不是说让用真实图片替换那个通用的图形嘛,这下有路径了,再看返回参数Drawable,好说啊,从一个网络地址获取Drawable没有直接方法,不过从一个流有啊,
/** * Create a drawable from an inputstream */ public static Drawable createFromStream(InputStream is, String srcName) { Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable"); try { return createFromResourceStream(null, null, is, srcName); } finally { Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); } }封装个方法以便以后使用(封装真的很重要)
Drawable getImageFromNetwork(String imageUrl) { URL myFileUrl = null; Drawable drawable = null; try { myFileUrl = new URL(imageUrl); } catch (MalformedURLException e) { e.printStackTrace(); } try { HttpURLConnection conn = (HttpURLConnection) myFileUrl .openConnection(); conn.setDoInput(true); conn.connect(); InputStream is = conn.getInputStream(); drawable = Drawable.createFromStream(is, null); is.close(); } catch (IOException e) { e.printStackTrace(); } return drawable; }好了,既然是读取网络上的图片就要考虑异步加载了,Android API > 9 (Honeycomb及之后)版本里,对UI线程/主线程里是不允许联网操作的,如果有网络操作,会抛出NetworkOnMainThreadException的异常,解决办法很简单,另起一个线程就可以了
new Thread(new Runnable() { Message msg = Message.obtain(); @Override public void run() { Html.ImageGetter imageGetter=new Html.ImageGetter() { @Override public Drawable getDrawable(String source) { Drawable drawable =getImageFromNetwork(source); drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight()); return drawable; } }; CharSequence charSequence = Html.fromHtml(html, imageGetter, null); msg.what = 0x101; msg.obj = charSequence; mHandler.sendMessage(msg); } }).start();在线程里边加载html并通过imageGetter把解析出来的src转成Drawable,并把CharSequence传出去,写到这基本上功能就实现了,运行一下,图片也出来了
然而这是个虾米啊。。图片怎么辣么一丢丢,这特么怎么看,一万只草泥马在奔腾,接着改吧,既然小那就放大放大放大~~
刚才实现的ImageGetter里边不是有setBounds嘛,改一下宽高就行了,
int screenWidth = getWindowManager().getDefaultDisplay().getWidth(); // 屏幕宽(像素,如:480px) int screenHeight = getWindowManager().getDefaultDisplay().getHeight(); // 屏幕高(像素, Log.e("getDefaultDisplay", "screenWidth=" + screenWidth + "; screenHeight=" + screenHeight); int w=screenWidth/2; int h=w/(drawable.getIntrinsicWidth()/drawable.getIntrinsicHeight()); drawable.setBounds(0,0,w,h);
宽取屏幕一半,高按原图比例缩放,到次才算大功告成,有什么不对的地方还请路过大神指导~
源码下载
相关文章推荐
- android点击事件,第一次无效,第二次才响应的问题
- Android设置Progress的颜色
- android 控制启动图标显示
- Android点击事件的四种实现 + 多击事件
- android 设置线程优先级 两种方式
- Android Drawable 那些不为人知的高效用法
- android获取系统环境变量
- Android权限参考
- Android软件开发之界面五大布局
- Android开发中实现用户注册和登陆的代码实例分享
- android局域网通信(三)
- android 获得屏幕宽度和高度
- Android 基础代码实例:音频 均衡器 示波器 声场 等
- 学Android---DatePicker&TimePicker
- Android应用开发的一般文件组织结构讲解
- android开发各种相关干货
- 在android studio中配置百度地图
- android 自定义view 流式布局
- android基础代码实例:录制视频
- Linphone android 最新版编译(解决android5.0以上无法运行问题)