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

android:gravity="center_vertical" 也设置了啊,然后猛然发现一行代码:android:lineSpacingExtra="8sp",原来是设置了这个行间距导致的。知道问题出在哪了,就好解决了,度娘还是看源码,都OK的啊。
先贴一下对比图

 解决之前的效果图:

  

解决之后的效果图:  


图文混排,不可缺少:SpannableString和ImageSpan,但是阅读源码发现,ImageSpan设置对齐方式只有两种:
  /**
* A constant indicating that the bottom of this span should be aligned
* with the bottom of the surrounding text, i.e., at the same level as the
* lowest descender in the text.
*/
public static final int ALIGN_BOTTOM = 0; /**
* A constant indicating that the bottom of this span should be aligned
* with the baseline of the surrounding text.
*/
public static final int ALIGN_BASELINE = 1;

要是ImageSpan能提供一个使其内容垂直居中的,问题不就轻松解决了吗,但是它没有提供了,****,再看,源码

ImageSpan是继承DynamicDrawableSpan的,而DynamicDrawableSpan中有两个这样的方法:getSize和draw,

 @Override
public int getSize(Paint paint, CharSequence text,
int start, int end,
Paint.FontMetricsInt fm) {
Drawable d = getCachedDrawable();
Rect rect = d.getBounds(); if (fm != null) {
fm.ascent = -rect.bottom;
fm.descent = 0; fm.top = fm.ascent;
fm.bottom = 0;
} return rect.right;
}
@Override
public void draw(Canvas canvas, CharSequence text,
int start, int end, float x,
int top, int y, int bottom, Paint paint) {
Drawable b = getCachedDrawable();
canvas.save(); int transY = bottom - b.getBounds().bottom;
if (mVerticalAlignment == ALIGN_BASELINE) {
transY -= paint.getFontMetricsInt().descent;
} canvas.translate(x, transY);
b.draw(canvas);
canvas.restore();
}

所以我们也可以自定义去实现,最后贴上代码:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.style.ImageSpan; import java.lang.ref.WeakReference; /**
* @Created SiberiaDante
* @Describe:
* @Time: 2017/8/18
* @Email: 994537867@qq.com
* @GitHub: https://github.com/SiberiaDante
*/ public class CenterAlignImageSpan extends ImageSpan { private WeakReference<Drawable> mDrawableRef; public CenterAlignImageSpan(Context context, Bitmap bitmap, int verticalAlignment) {
super(context, bitmap, verticalAlignment);
} public CenterAlignImageSpan(Context context, int resId, int verticalAlignment) {
super(context, resId, verticalAlignment);
} @Override
public int getSize(Paint paint, CharSequence text, int start, int end,
Paint.FontMetricsInt fontMetricsInt) {
Drawable drawable = getDrawable();
Rect rect = drawable.getBounds();
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;
} @Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y,
int bottom, Paint paint) {
Drawable drawable = getCachedDrawable();
canvas.save();
Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
int fontHeight = fmPaint.descent - fmPaint.ascent;
int centerY = y + fmPaint.descent - fontHeight / 2;
int transY = centerY - (drawable.getBounds().bottom - drawable.getBounds().top) / 2;
canvas.translate(x, transY);
drawable.draw(canvas);
canvas.restore();
} private Drawable getCachedDrawable() {
WeakReference<Drawable> wr = mDrawableRef;
Drawable d = null;
if (wr != null) {
d = wr.get();
} if (d == null) {
d = getDrawable();
mDrawableRef = new WeakReference<>(d);
} return d;
}
}

最后:

 SpannableString spannableStringCustom = new SpannableString("测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排测试图文混排");
CenterAlignImageSpan span = new CenterAlignImageSpan(this, R.mipmap.ic_launcher, ImageSpan.ALIGN_BASELINE);//重写的ImageSpan
spannableStringCustom.setSpan(span, 0, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textViewCustom.setText(spannableStringCustom);

参考文章:https://segmentfault.com/a/1190000007133405

Android TextView中图文混排设置行间距导致高度不一致问题解决的更多相关文章

  1. 【转】Android TextView SpannableStringBuilder 图文混排颜色斜体粗体下划线删除线

    spannableStringBuilder 用法详解: SpannableString ss = new SpannableString("红色打电话斜体删除线绿色下划线图片:." ...

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

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

  3. android开发 自定义图文混排控件

    功能:图文混排,可自动缩放字体,如图: 单点触控使用的代码来自:http://blog.csdn.net/xiaanming/article/details/42833893  谢谢博主! 在该dem ...

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

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

  5. 使用android SpannableStringBuilder实现图文混排,看到许多其他

    项目开发需要达到这种效果 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmFuY3lsb3ZlamF2YQ==/font/5a6L5L2T/fontsiz ...

  6. 【转】关于FLASH中图文混排聊天框的小结

    原文链接 图文混排也是FLASH里一个很古老的话题了,我们不像美国佬那样游戏里面聊天框就是聊天框,全是文字干干净净,也不像日本人发明了并且频繁地使用颜文字.不管是做论坛.做游戏,必定要实现的一点就是带 ...

  7. iOS中 图文混排/自定义图文混排 作者:韩俊强

    指示根视图:(准备几张图片,把label加载在window上) CustomLable *label = [[CustomLable alloc]initWithFrame:CGRectMake(0, ...

  8. CSS - 关于li中图文混排不能垂直居中的问题

    图片和文字一起放在li标签下不能同时垂直居中   解决办法: 1.设置图片的position:absolute; 2.把文字加上span标签: span{ height:30px;line-heigh ...

  9. 自定义图文混排视图MyImageTextView

    http://blog.csdn.net/xujunfeng000/article/details/36399339?utm_source=tuicool&utm_medium=referra ...

随机推荐

  1. mapreduce设置setMapOutputKeyClass与setMapOutputValueClass原因

    一般的mapreduce的wordcount程序如下: public class WcMapper extends Mapper<LongWritable, Text, Text, LongWr ...

  2. shiro实战系列(十)之Subject

    毫无疑问,在 Apache Shiro 中最重要的概念就是 Subject.'Subject'仅仅是一个安全术语,是指应用程序用户的特定 安全的“视图”.一个 Shiro Subject 实例代表了一 ...

  3. table border

    table的CSS为{border-collapse:collapse;border:none;},再设置td的CSS为{border:solid#000 1px;}是一个非常不错的方法. 示例: & ...

  4. 筛选法求N以内的所有素数

    素数:一个数只能被1和它本身整除的数.2是最小的素数 #include <iostream> using namespace std; #define NUM 100 ]; int mai ...

  5. jquery操作checked

    jquery操作checkbox,如何获取勾选状态?如何使得勾选?如何取消勾选? 来段代码就知道了: <html> <head> <meta charset=" ...

  6. Linux下离线安装Docker

    Linux下离线安装Docker 一.基础环境 1.操作系统:CentOS 7.3 2.Docker版本:18.06.1 官方下载地址(打不开可能需要***) 3.百度云Docker 18.06.1地 ...

  7. zookeeper的原理及使用

    ZooKeeper是Hadoop Ecosystem中非常重要的组件,它的主要功能是为分布式系统提供一致性协调(Coordination)服务,与之对应的Google的类似服务叫Chubby.今天这篇 ...

  8. 20155307《网络对抗》Web安全基础实践

    20155307<网络对抗>Web安全基础实践 基础问题回答 SQL注入攻击原理,如何防御? 原理:SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL ...

  9. 2017-2018-4 20155317《网络对抗技术》EXP3 免杀原理与实践

    2017-2018-4 20155317<网络对抗技术>EXP3 免杀原理与实践 一.问题回答 (1)杀软是如何检测出恶意代码的?杀软是通过代码特征比对得出的,将检查的代码和自己的特征库的 ...

  10. jsp页面中日期的格式化

            在一次开发中,由于数据库中生日采用的是datetime的数据类型,因此数据库中数据格式为:2017-07-11 00:00:00. 但是,编辑页面中回显生日肯定是不可以显示出时分秒的, ...