Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 676|回复: 0

Android TextView中图文混排设置行间距导致高度不一致问题解决

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-6-29 01:50:41 | 显示全部楼层 |阅读模式

    最近项目中需要实现一个评论带表情的功能,刚开始一切顺利,非常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

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-1-11 14:52 , Processed in 0.060066 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表