Android中文图混排时文图的居中对齐 FontMetrics以及自定义ImageSpan实现
文章转自:http://www.sohu.com/a/150059234_611601
本文作者CnPeng的博客地址:
http://www.jianshu.com/p/2650357f7547
这个标题有点长,乍一看这么个标题你可能没明白啥意思,且听我慢慢道来。
公司的项目中新增了一个“心动” 的功能,用户初次使用时需要给一个引导页,就是下面图中的这个样子(这就是做完之后的效果了)。
在上图中整体实现的时候使用的是popUpWindow。
该popupWindow整体使用相对布局,里面再用一个相对布局布局嵌套了三个TextView:"啊哦。。。。pass" 用一个TextView,中间灰色的上传头像的提示用了一个TextView,底部“我知道了” 也是一个TextView。
上面的左划示意图使用above 放在 包含TextView的相对布局上方,并通过负的margin值将它下移并覆盖在包含TextView相对布局上。
这个界面并没有什么难度,这里重点说的是第一个TextView中的图文混排,并让图片的横向中间线与该行文字的横向中间线对齐,也就是说,让文字与那个�� 图片的中间在水平方向对齐。
1
图文混排的方式有哪些?
通常我们向TextView中插入图片实现图文混排有如下方式:
1. 使用drawableLeft等属性设置,这种方式对应的java方法是 setCompoundDrawablesWithIntrinsicBounds(leftDrawble,topDrawable,rightDrawable,bottomDrawable);
2. 使用 SpannableString ,先将图片转成ImageSpan对象,然后通过setSpan插入到SpannableString 中,最后再将SpannableString通过setText设置给TextView。(SpannableString 继承自CharSquence)
3. 此外,还有一种利用Html.ImageGetter格式化图片的方式。(截止目前为止,我没用过这种方式,如果想了解的话,可以参考http://wangleyiang.iteye.com/blog/1771439中的第二点)
2
使用SpannableString+ImageSpan怎么实现图文混排?
(1)基本实现方式
效果图如下:
实现方式很简单,我们只需要在xml布局文件中定义一个TextView,然后在代码中获取该TextView并创建一个含有图片的SpannableString,并将该SpannableString通过setText( )设置给TextView即可。
代码如下:
xml布局文件中只给了一个普通的TextView,代码省略。
在上面的代码中,我们通过ImageSpan的构造方法得到了一个ImageSpan对象。该构造方法中传入的两个参数分别是上下文和图片的id。(imageSpan的构造方法还有很多)
SpannbaleString的setSpan方法中,传入的四个参数分别是 ImageSpan对象、将ImageSpan插入到的起始位置(start)、将ImageSpan插入到的终点位置(end)、是否应用字体样式。
具体将ImageSpan对象插入到哪个位置,由第二个和第三个参数确定,插入的时候会覆盖从 start 位置开始(不包含该位置)到终止位置间的内容(包含该位置)。
第四个参数是在你插入文本的时候使用的,用来控制新插入的文本与已有文本内容的字体样式是否一致的如果你插入的是图片,这里就可以随便选择一种模式。
经过上面虽然实现了图文混排,但是,细心的你可能发现了,这时候的文字和图片是基于底部对齐的(由于图片的原因,图片底部与边框有一点点的间距)。那么如果我想更改对齐方式怎么办呢?
(2)更改图片与文本的对齐方式--ALIGN_BASELINE对齐
设置对齐方式的方法很简单,在构造ImageSpan对象的时候,传入第三个参数ALIGN_BASELINE 即可,代码如下:
ImageSpan imageSpan = new ImageSpan(this, R.mipmap.ic_launcher, DynamicDrawableSpan.ALIGN_BASELINE);
设置对齐方式为ALIGN_BASELINE后的效果图:
咦,看着跟上面的图没啥区别啊?那么我再把上面没设置对齐方式的图拉下来看下:
仔细对比下,我们发现,设置对齐方式之后,图往上跑了一点点。
其实,在ImageSpan 中,官方只给出了两中对齐方式:
一种是 ALIGN_BOTTOM , 表示与文字内容的底部对齐,如果在构造ImageSpan时没有传入对齐方式,那么默认就是这种底部对齐。
另一中就是 ALIGN_BASELINE, 表示与文字内容的基线对齐。那么,你可能会问我基线是啥?请继续往下看:
3
Paint.FontMetrics 是啥?
(1) Paint.FontMetrics基本介绍
要说基线呢,我们先了解这个Paint.FontMetircs, 官方对该类的解释是:Class that describes the various metrics for a font at a given text size., 意思是说,这玩意儿是绘制文本内容时存储该文本内容位置信息的一个类。这个类中有如下五个字段:
(2) BaseLine 基线到底是啥?
上图中这5个字段除了leading 外,其他四个都是相对于 基线BaseLine来确定的,那么,到底啥是基线??
先来看一张图:
如上图,标准的英文书写是基于四线三格,其中,我们书写英文的时候,都是以第三条线为基准,也就是说,基线就是这个四线三格中的第三条线!!
(3)Paint.FontMetrics中字段的含义及示意图
官方文档中对这几个字段的解释很简单,但理解起来挺费劲,直接上图,图中的标注都是跑代码之后确定的,如果有不准确的地方,欢迎指正:
根据上图可知:
ascent
文字内容的顶部到基线的距离。即 ascent=文字内容顶部Y坐标 - 基线Y坐标。由于android中坐标系是 右下为正,所以得到的ascent实际是一个负数。
descent
文字内容的底部到基线的距离。即 descent=文字内容底部Y坐标 - 基线Y坐标。
基线
在图中,基线的坐标用Y表示,在ImageSpan父类的 draw( ) 中,会传入一个 float Y ,就是这个基线的坐标。实际上,基线的Y坐标=文字内容中间线Y坐标+1/2 (文字内容高度)
top
对应图中 文字所在行的top 坐标
bottom
对应图中 文字所在行的bottom 坐标
需要注意:如果设置了行间距,且文本内容产生了换行,那么这个bottom 也会将行间距包裹。所以, 图中蓝色的文字内容中间线的Y轴坐标并不一定等于 (bottom+top)/2
4
自定义ImageSpan实现文字与图片居中对齐
好了,前面说了那么多,终于进入正题了。。。
在上面的2 SpannableString+ImageSpan实现图文混排中,我们已经知道官方并没有给出文字与图片居中对齐的模式,所以需要我们自定义。
关于自定义ImageSpan的分析,已经有前辈讲解过了,此处不再赘述,请参考http://blog.csdn.net/gaoyucindy/article/details/39473135。
但是,按照该文章中的代码实现的时候,有个问题就是:如果给TextView设置了行间距,且文本产生了换行,那么就无法对齐了!!
那么,设置了行间距之后,该如何实现文本和图片的居中对齐呢?也有前辈分析过了,请看:http://www.cnblogs.com/withwind318/p/5541267.html, 但是,这篇文章中的实现方式没有重写 getSize( ) 方法,所以也有一个问题:文本和图片并不是在TextView的居中位置,而且如果图片高于文本的话,图片会显示不全!!如下图:
参考了那么多了,终于该给出我的终极方案了!!
根据上面链接中两位前辈的分析,其实我们自定义的时候,需要做的事情是 获取文本内容的中间线以及图片的中间线,然后获取两者差值,然后在draw方法中绘制图片时将差值作为canvas.translate(x, transY) 中的transY;同时要重写 getSize( )。
这样最终实现的效果是,不论是否设置行间距,不论图片大于文本还是文本大于图片,都能实现文本和图片的居中对齐!
看最终效果图:
上代码:
在Activity中使用:
xml布局文件:
上面的已经是完整代码了,如果想直接下载运行,请到gitHub下载:https://github.com/CnPeng/CrazyAndroid
该仓库中的b_01_spannableString_ImageSpan 对应该文中的内容
写在最后,最近项目太紧了,过了年一直在加班。这次的总结也很仓促,本来想写的更细一些,并且也想把SpannableString的使用完整总结,but 时间太紧了,先这样吧,后面时间充足了再修正吧!
欢迎各位指正文中错误的地方,一起交流,一起进步!
参考链接:
http://wangleyiang.iteye.com/blog/1771439
http://blog.csdn.net/gaoyucindy/article/details/39473135
http://www.cnblogs.com/withwind318/p/5541267.html
http://stackoverflow.com/questions/27631736/meaning-of-top-ascentbaseline-descent-bottom-and-leading-in-androids-font
https://github.com/GcsSloop/AndroidNote/blob/master/CustomView/Advance/%5B99%5DDrawText.md
Android中文图混排时文图的居中对齐 FontMetrics以及自定义ImageSpan实现相关推荐
- Android阿拉伯语混排
文章目录 1.Android阿拉伯语混排显示关键类 BidiFormatter 1.示例一 测试一 测试二 测试三 测试三 测试四 测试五 2. 示例二 3. 示例三 4. 示例四 2.关于实现上面功 ...
- Android动态图文混排,Android控件TextView实现静态图与动态GIF图文混排
最近做项目功能时,需要在TextView中展示图文,刚开始做的时候以为很简单,只需要用个ImageView跟TextView来展示就行了,可是发现这样做,不能实现我们需要的效果,这就需要涉及到富文本T ...
- android多媒体图文混排,干货!!!Android富文本实现图文混排
效果图 rich.jpg 像图中的效果,大家在开发并不少见,大家可能不知道android提供了实现图文混排的类.大家或许会写一个布局或者使用drawableLeft这个属性实现文本的左侧图标. and ...
- Android 动态图文混排的常用方法
2019独角兽企业重金招聘Python工程师标准>>> DrawableIcon的设置 对于TextView或者EditText动态设置drawableLeft,drawableRi ...
- android多媒体图文混排,android图文混排
背景 最近我们的产品来了个新的模块,给学生做题提高成绩的.需求如下: 支持单选.多选.填空题 支持图片文字混排 输入框有交互,排版精致美观 为了体验优化,不能使用网页实现效果 思路分析 我们的图文混排 ...
- LaTex输入中文英文混排[overleaf]
\documentclass{ctexart} \begin{document} \tableofcontents\begin{abstract} 这是简介及摘要. \end{abstract}\se ...
- cad超级排孔_家具cad排孔图 爆破排孔图
求一张板式家具CAD图,设计图,下料,排孔,安装图. 此外... 您可以使用正方形软件绘制家具效果图,可以使用3d max,还可以使用AUTO CAD绘制平面图.剖面图.效果图和三维线图.如果想省事, ...
- 解决Android TextView中英文混排换行问题
文章目录 个人极不建议这样做(之后会说原因) 1 现象 2 解决思路 3不推荐的原因 个人极不建议这样做(之后会说原因) 1 现象 绿色底黄色框内的就是原生TextView出现的情况,出现这种情况的主 ...
- android 之图文混排+GridView
实例代码: package com.hsj.example.gridviewdemo01;import android.app.ProgressDialog; import android.graph ...
最新文章
- Linux内核情景分析之异常访问,用户堆栈的扩展
- UVa --10566
- localsandbox 如何响应tile点击事件
- 初步认识迭代服务器和并发服务器
- 安装配置nagios
- python中string.digits_Python3基础:String模块ascii_letters和digits
- ibm336服务器显示brd,ibmx3850x5服务器故障BRD报警|升级主板微码
- 42道计算机网络面试高频题+答案,面试官喜欢的答案都在这里
- 王道中数据结构的排序算法
- 根据制备方法划分不同的壳聚糖水凝胶
- 167. 两数之和 II - 输入有序数组(java)
- Mac搭建本地局域网SVN服务(Cornerstone)
- 弘辽科技:拼多多转化率怎么看?4个步骤教会你
- 【睡服】自动化面试官,就用2020年最全的自动化测试面试题及答案
- [转载]刘兴亮|给同一天发的这三款社交产品算算命
- 微信全面开放个人免费版红包封面!
- Tensorflow2.0之用循环神经网络生成周杰伦歌词
- 无线网卡无法与计算机usb,台式电脑主机安装USB无线网卡使用不了WiFi网络怎么办?...
- ncut matlab,matlab call Ncut: Matrix is too large to convert to linear index.
- C语言实现天气获取 + HTML页面
热门文章
- Task.Factory.StartNewTResult 和 Task.RunTResult 到底有什么区别?
- Dapr牵手.NET学习笔记:绑定
- 记一次 .NET 某电商定向爬虫 内存碎片化分析
- 你知道哪些开源基金会?
- 网络协议,没有想象中那么难
- .NET斗鱼直播弹幕客户端(2021)
- 探索.NET平台中的SIMD内在函数Vector
- IdentityServer 部署踩坑记
- asp.net core 使用newtonsoft完美序列化WebApi返回的ValueTuple
- [ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [上篇]