经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
TextView图文混排
来源:cnblogs  作者:妖久  时间:2018/11/20 19:45:49  对本文有异议

大家都知道,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类型的实例; 
startend标记要替代的文字内容的范围; 
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. public static final int ALIGN_CENTER = 2;
  3. public MyImageSpan(Drawable d, int verticalAlignment) {
  4. super(d, verticalAlignment);
  5. }
  6. @Override
  7. public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
  8. Drawable b = getDrawable();
  9. canvas.save();
  10. Paint.FontMetricsInt fm = paint.getFontMetricsInt();
  11. //系统默认为ALIGN_BOTTOM
  12. int transY = bottom - b.getBounds().bottom;
  13. if (mVerticalAlignment == ALIGN_BASELINE) {
  14. transY -= fm.descent;
  15. } else {
  16. transY = ((y + fm.descent + y + fm.ascent) / 2
  17. - b.getBounds().bottom / 2);
  18. }
  19. canvas.translate(x, transY);
  20. b.draw(canvas);
  21. canvas.restore();
  22. }
  23. @Override
  24. public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
  25. Drawable b = getDrawable();
  26. Rect rect = b.getBounds();
  27. if (fm != null) {
  28. Paint.FontMetricsInt painFm = paint.getFontMetricsInt();
  29. int fontHeight = (painFm.bottom - painFm.top);
  30. int drHeight = rect.bottom - rect.top;
  31. int top = drHeight / 2 - fontHeight / 4;
  32. int bottom = drHeight / 2 + fontHeight / 4;
  33. fm.ascent = -bottom;
  34. fm.top = -bottom;
  35. fm.bottom = top;
  36. fm.descent = top;
  37. }
  38. return rect.right;
  39. }
  40. }

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

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

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号