最近项目中需要实现一个评论带表情的功能,刚开始一切顺利,非常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. 【洛谷】【单调栈】P1901 发射站

    [题目描述:] 某地有 N 个能量发射站排成一行,每个发射站 i 都有不相同的高度 Hi,并能向两边(当 然两端的只能向一边)同时发射能量值为 Vi 的能量,并且发出的能量只被两边最近的且比 它高的发 ...

  2. android studio 导入module作为lib使用

    1.将 android module导入 android project 中  2.在要作为lib导入的module 的build.gradle文件中添加一行 “apply plugin: ‘andr ...

  3. go变量和常量

    一.变量 1. 命名规则:字母或者_下划线开头 2.“:=” 这种模式只能用于函数内部,常量const不能用这种模式来定义 二.常量 1. 常量const必须在定义的时候就赋值 2. 常量的值在整个过 ...

  4. OC4J Configuration issue. /u01...dbhome_1/oc4j/j2ee/OC4J_DBConsole_orcl-db-01_orcl not found.

    emctl start dbconsole 报错信息: OC4J Configuration issue. /u01/app/Oracle/product/11.2.0/dbhome_1/oc4j/j ...

  5. Android 在测试阶段当出现多个测试服务器地址时打包的小技巧

    前提:服务端没有做特殊处理 在开发android网络客户端项目时,不可避免的会用到“测试服务器地址”和“云端服务器地址”等.(有时可能会有多个) 这时在打包给测试那帮哥们时,你就需要一个服务器地址打上 ...

  6. log下一次改版优化别人代码的事

    有次接到个PM要改版一个功能的UI设计,前端童鞋还没敲定页面的时候,我先看了看这个功能的后台,我擦...简直是惨不忍睹..对PM来说是改版UI,对我这么有点代码洁癖的来说就是优化代码. 首先我能肯定的 ...

  7. R语言--输入输出

    基本输入输出 输入: readline, edit, fix 输出: print, cat 输出重定向 sink #基本输入输出 x=readline('请输入:') #读取输入,一行为一个字符串 x ...

  8. 在win10环境中安装xilinx vivado IDE时出现的问题及解决方法

    1.问题:There is no valid Xilinx installation that this Update can be applied to. 解决方法一:下载的是更新包,如果设备没有预 ...

  9. 利用IDA6.6进行apk dex代码动态调试

    网上公开IDA6.6已经有一段时间,这个版本有个好处就是可以动态调试java代码.正好现在需要动态调试,所以顺便练习一下. 根据android的官方文档,如果要调试一个apk里面的dex代码,必须满足 ...

  10. 20155305《网络对抗》Web安全基础实践

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