自我感觉做什么事情都是事倍功半,同样性格还是丢三落四的人。记录每一次解决问题的思路经过,以供自我学
前几天让做一个效果如上图,于是引发了一些列的思路风暴:
(思路1)
TextView+Html的形式:html在网页实现很常见的,所以不免第一个反应就是用html。于是让前端哥们写了一段html文本,但是当我用着个文本显示的时候发现没有效果,于是开始想是不是因为哥们用的CSS3.0,html5的原因(因为可能手机的TextView不支持,所以可能是这原因),然后去网上搜索看TextView都支持什么html标签,最后发现TextView支持有限的Html标签,其中知识一些简单的字体,颜色,背景,还不支持CSS(更不用说CSS3.0了)
思路1总结:整个过程耗费了半个下午,其中还包括1一个人情(前端哥们的帮忙) 。查询TextView具体支持标签在Html.from("")的方法中查找
知识点总结:TextView支持的html很是有限的,关于字体的样式还是用自个的标签<font>。而且最后html会被转换span的形式
(思路2)ImageScpan+自定义drawable方式:textview+html不行,那么,只能用span。为什么使用ImageSpan原因:1,因为可以把“服务中”这个块当成图片。如果用ImageScpan实现了的话,后期可以随便换成任何图片。2。不使用ImageSpan的话,只能使用backgroundscpan,relativespan和字体颜色span等至少三个集合,有点多了感觉,最重要的是Imagespan是可以到行尾部换行了(解释:如果行尾的预留的宽度不够的话,会另起一行。所选文字对于一个图片块),不知道其他的行不行(解释:字面意思backgroundspan只是改变所选文章的背景色,所针对的文字还是一个对一个。另外两个span一样的)。使用imagespan+图片的形式是合理的选择,既然这个形式的话那么imagespan+自定义的drawable是最好的思路出现了,这里是因为自定义drawable可以绘制任何图片。于是要自个实现一个drawable和系统的imagespan组装这个效果。到这里以为终于可以了,走几步才发现,嘿嘿...
系统的Imagescpan不行,不能和文字垂直居中,并且当所使用图片高度大于文字的ascent(。好像是这个。 )时,改行的行高使用会加上一定高度。于是上网搜索垂直居中ImageScpan 。
思路2总结:整个过程进展也算合理。最后的结果是:搜索的垂直居中imagescpan+自定义drawable。(出错了,为什么不直接写一个自定义自个的Imagescpan呢)工作量相对多,自定义两个东西
知识点总结:
1,系统的Imagescpan不行,不能和文字垂直居中,并且当所使用图片高度大于文字的ascent(。好像是这个。 )时,改行的行高使用会加上一定高度。于是上网搜索垂直居中ImageScpan 。
2,牵扯到了drawable自定义 ,了解到当drawable.draw(canvas)之前 drawable.getbouds返回的区域必须是有个有空间的区域。不能是高为0,宽为0,这样的话只会看不到
3,中间搜索到了一个大神写的垂直居中的ImageSpan
(思路3) 自定义自个的ImageSpan:直接自定义自个的span,抛弃了思路2还用自个写自定义drawable,显然这个是不错的。直接朝这个方向前进吧!!最后完成了效果
思路3总结:canvas.drawline的时候水平线应该是字体的baseline的位置。
针对这个问题最终总结:
1, 是因为自个不知道textview支持多少html标签,所以有了思路1。途中得到的战果
TextView支持的html很是有限的,关于字体的样式还是用自个的标签。而且最后html会被转换span的形式
2, 为什么会出现思路2的情况,有两个需要自定义的类,是因为当时大脑乱纠结这个问题太长时间了。没想过直接二合一直接自定义一个 途中得到的战果
献上最后的两个重要的ImageSpan网上搜索的某个大神:
public class VerticalImageSpan extends ImageSpan { //根据图片调整字体,来是适应图片的高度 public VerticalImageSpan(Context context,int drawableid) { super(context,drawableid); } /** * update the text line height */ @Override public int getSize(Paint paint,CharSequence text, intstart, intend, Paint.FontMetricsInt fontMetricsInt) { //设置图片块的宽度 Drawable drawable = getDrawable(); Rect rect = drawable.getBounds(); //注意点,这个rect应该是有效的空间 高度为0,宽度为0 drawable就绘制不出来,在这个地方是用 if(fontMetricsInt !=null) { //来调整字体高度的,因为要让文本行适应图片高度 Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt(); int fontHeight = fmPaint.descent- fmPaint.ascent; int drHeight = rect.bottom- rect.top; int centerY = fmPaint.ascent+ fontHeight /2; fontMetricsInt.ascent= centerY - drHeight /2; fontMetricsInt.top= fontMetricsInt.ascent; fontMetricsInt.bottom= centerY + drHeight /2; fontMetricsInt.descent= fontMetricsInt.bottom; } return rect.right; } /** * see detail message in android.text.TextLine * *@paramcanvasthe canvas, can be null if not rendering *@paramtextthe text to be draw *@paramstartthe text start position *@paramendthe text end position *@paramxthe edge of the replacement closest to the leading margin *@paramtopthe top of the line //文本所在改行的顶部 *@paramythe baseline //文本的基准线 *@parambottomthe bottom of the line //文本所在改行的底部 及下行的顶部,xml文件中的设置的行间距会直接影响 bottom到baseline的距离 *@parampaintthe work paint */ @Override public void draw(Canvas canvas,CharSequence text, int start, int end, float x, int top, inty, int bottom,Paint paint) { CharSequence targetText=text.subSequence(start,end); Log.v("文字",targetText.toString()); Drawable drawable = getDrawable(); canvas.save(); Rect rect =drawable.getBounds(); //注意点,这个rect应该是有效的空间 高度为0,宽度为0 drawable就绘制不出来, Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt(); int fontHeight = fmPaint.descent- fmPaint.ascent; int centerY = y + fmPaint.descent- fontHeight /2; int transY = centerY - (rect.bottom- rect.top) /2; canvas.translate(x,transY); drawable.draw(canvas); canvas.restore(); } }