大家都知道,textView有一个setCompoundDrawables的方法来设置上下左右位置的图标,当然,也可以在xml布局文件中设置,然而问题来了,假如我们把图标放在左边,当我们让TextView分多行显示的时候,会出现一种情况,左边的图标并不会与第一行对齐,而是与整个textView居中对齐。

即我们要的是下图:

结果是这个图:

怎么办呢?我们可以用图文混排:

我们可以利用SpannableString和ImageSpan。

1、构建SpannableString对象。

  1. SpannableString spanString = new SpannableString(textView.getText().toString());

2、获取Drawable对象,即将我们的图案转换为Drawable对象,并设置大小。

  1. Drawable tvDrawable = ContextCompat.getDrawable(mContext, R.drawable.pic);
  2. tvDrawable.setBounds(0, 0, tvDrawable.getMinimumWidth(), tvDrawable.getMinimumHeight());

3、构建ImageSpan 对象

  1. ImageSpan span = new ImageSpan(tvDrawable, ImageSpan.ALIGN_BASELINE);

 4、设置给上面的SpannableString对象

  1. spanString.setSpan(span, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

5、最终设置给TextView

  1. textView.setText(spanString)

加下来讲讲上面的方法:

1、ImageSpan对象,第二个参数为图像与文字的对齐方式,ImageSpan只带有两个对齐方式,分别是:ALIGN_BASELINE、ALIGN_BOTTOM。

ALIGN_BOTTOM 表示与文字内容的底部对齐,如果在构造ImageSpan时没有传入对齐方式,那么默认就是这种底部对齐。

ALIGN_BASELINE, 表示与文字内容的基线对齐

  1. ImageSpan Span = new ImageSpan(tvDrawable, ImageSpan.ALIGN_BASELINE);

2、setSpan()方法

  1. public void setSpan(Object what, int start, int end, int flags) {
  2. super.setSpan(what, start, end, flags);
  3. }

what传入各种Span类型的实例; 
start和end标记要替代的文字内容的范围; 
flags是用来标识在Span范围内的文本前后输入新的字符时是否把它们也应用这个效果,它有如下几个:

Spanned.SPAN_EXCLUSIVE_EXCLUSIVE、

Spanned.SPAN_INCLUSIVE_EXCLUSIVE、

Spanned.SPAN_EXCLUSIVE_INCLUSIVE、

Spanned.SPAN_INCLUSIVE_INCLUSIVE

INCLUSIVE表示应用该效果,EXCLUSIVE表示不应用该效果,如Spanned.SPAN_INCLUSIVE_EXCLUSIVE表示对前面的文字应用该效果,而对后面的文字不应用该效果。

坑:

1、既然ImageSpan只带有两个对齐方式,那我们需要自己实现居中对齐:

  1. class MyImageSpan extends ImageSpan {
  2.  
  3. public static final int ALIGN_CENTER = 2;
  4.  
  5. public MyImageSpan(Drawable d, int verticalAlignment) {
  6. super(d, verticalAlignment);
  7. }
  8.  
  9. @Override
  10. public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
  11. Drawable b = getDrawable();
  12. canvas.save();
  13.  
  14. Paint.FontMetricsInt fm = paint.getFontMetricsInt();
  15.  
  16. //系统默认为ALIGN_BOTTOM
  17. int transY = bottom - b.getBounds().bottom;
  18. if (mVerticalAlignment == ALIGN_BASELINE) {
  19. transY -= fm.descent;
  20. } else {
  21. transY = ((y + fm.descent + y + fm.ascent) / 2
  22. - b.getBounds().bottom / 2);
  23. }
  24. canvas.translate(x, transY);
  25. b.draw(canvas);
  26. canvas.restore();
  27. }
  28.  
  29. @Override
  30. public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
  31. Drawable b = getDrawable();
  32. Rect rect = b.getBounds();
  33. if (fm != null) {
  34. Paint.FontMetricsInt painFm = paint.getFontMetricsInt();
  35. int fontHeight = (painFm.bottom - painFm.top);
  36. int drHeight = rect.bottom - rect.top;
  37.  
  38. int top = drHeight / 2 - fontHeight / 4;
  39. int bottom = drHeight / 2 + fontHeight / 4;
  40.  
  41. fm.ascent = -bottom;
  42. fm.top = -bottom;
  43. fm.bottom = top;
  44. fm.descent = top;
  45. }
  46. return rect.right;
  47. }
  48. }

为何上面的自定义能够实现居中对齐呢?首先要了解Paint.FontMetrics。

请看另一篇博客:https://www.cnblogs.com/tangZH/p/8692910.html

出自:http://77blogs.com/?p=491

TextView图文混排的更多相关文章

  1. TextView + Spanned实现图文混排以及图片点击交互

    最近要实现图文混排的需求,webview过大,所以想到了用SpannableStringBuilder来实现. 不过参考了大量国内文章,大多数是教你如何实现图文混排,并没有提及图片点击交互的.有翻阅了 ...

  2. Android 自绘TextView解决提前换行问题,支持图文混排

    先看下效果图: 上面是MTextView,下面是默认的TextView. 一.原因 用最简单的全英文句子为例,如果有一个很长的单词,这一行剩余的空间显示不下了,那么规则就是不打断单词,而是把整个单词丢 ...

  3. Android TextView中图文混排设置行间距导致高度不一致问题解决

    最近项目中需要实现一个评论带表情的功能,刚开始一切顺利,非常easy,突然有一天发现文字跟表情混排的时候,TextView中图文高度不一致,excuse...什么鬼,之前明明测试过图文混排,不存在这个 ...

  4. Android中Textview显示Html,图文混排,支持图片点击放大

    本文首发于网易云社区 对于呈现Html文本来说,Android提供的Webview控件可以得到很好的效果,但使用Webview控件的弊端是效率相对比较低,对于呈现简单的html文本的话,杀鸡不必使用牛 ...

  5. android:怎样在TextView实现图文混排

    我们通常在TextView文本中设置文字.但是怎样设置图文混排呢? 我就在这里写一个样例 .我们须要用到一点简单的HTML知识 在TextView中预订了一些类似HTML的标签,通过标签能够使Text ...

  6. 用NSAttributedString实现简单的图文混排

    iOS7以后,因为TextKit的强大,可以用NSAttributedString很方便的实现图文混排(主要是利用了NSTextAttachment). 关于Textkit的牛逼之处,可以参考objc ...

  7. ListView异步加载图片,完美实现图文混排

    昨天参加一个面试,面试官让当场写一个类似于新闻列表的页面,文本数据和图片都从网络上获取,想起我还没写过ListView异步加载图片并实现图文混排效果的文章,so,今天就来写一下,介绍一下经验. Lis ...

  8. UITextView实现图文混排效果

    用UITextView实现图文混排效果的展示,首先要禁用UITextView的编辑功能,将属性editable设置为NO 1.首先创建一个NSTextAttachment对象,这个对象有一个image ...

  9. 使用android SpannableStringBuilder实现图文混排

    项目开发中需要实现这种效果 多余两行,两行最后是省略号,省略号后面是下拉更多 之前用过的是Html.fromHtml去处理图文混排的,仅仅是文字后图片或者文字颜色字体什么的, 但是这里需要在最后文字的 ...

随机推荐

  1. [Swift]LeetCode23. 合并K个排序链表 | Merge k Sorted Lists

    Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. E ...

  2. [Swift]LeetCode168. Excel表列名称 | Excel Sheet Column Title

    Given a positive integer, return its corresponding column title as appear in an Excel sheet. For exa ...

  3. iOS学习——浅谈RunLoop

    RunLoop的字面意思是运行循环.跑圈,一个App启动后能一直执行,就是因为启动后进入了一个循环,在这个循环中不断监听各种状态.手势动作,并做出相应的响应.这个循环就是我们今天要探究的RunLoop ...

  4. logback.xml sql语句输出

    在使用springBoot框架之后,日志配置文件变成了logback.xml,输出sql语句的方法为: <!-- 打印sql语句 --> <logger name="com ...

  5. Python内置函数(26)——globals

    英文文档: globals() Return a dictionary representing the current global symbol table. This is always the ...

  6. Windows提权与开启远程连接

    1.提权: 建立普通用户:net user 帐户 密码 /add 提权成管理员:net localgroup administrators 帐户 /add 更改用户密码:net user 帐户 密码 ...

  7. asp.net core系列 35 EF保存数据(2) -- EF系列结束

    一.事务 (1) 事务接着上篇继续讲完.如果使用了多种数据访问技术,来访问关系型数据库,则可能希望在这些不同技术所执行的操作之间共享事务.下面示例显示了如何在同一事务中执行 ADO.NET SqlCl ...

  8. Chapter 5 Blood Type——28

    Mike came through the door then, glancing from me to Edward. 然后Mike从门里走出来,看了一眼我和Edward The look he g ...

  9. 看板中的WIP限制

    WIP限制并不是真的要限制你的进度,事实上正相反. 什么是WIP限制? 在敏捷开发中,WIP限制决定了每种情况下的工作流中可以存续的最大工作量.限制进行中的工作数量可以更容易辨识团队工作流中的无效工作 ...

  10. Windows证书操作

    查看证书 在快捷命令栏输入mmc打开控制台 选择文件-->添加或删除管理单元 添加,选择计算机账户,本地计算机 添加完成证书后可以将localhost证书删除 生成localhost证书 打开v ...