解决Android 系统中 文字 + ImageSpan 对齐问题。

使用接口:
    public CharSequence addEmojiSpans(CharSequence text) {
        SpannableStringBuilder builder = new SpannableStringBuilder(text);

        // Scan for both Softbank private Unicode emoji code points (every
        // Android SMS app + iOS < 5) and Unicode 6.1 emoji BMP and non-BMP
        // codes
        Matcher matcher = mPattern.matcher(text);
        while (matcher.find()) {
            setMatcherEndPosition(matcher.end());
            int resId = mSmileyToRes.get(matcher.group());
            ImageSpanAlignCenter img = new ImageSpanAlignCenter(mContext,resId);
            builder.setSpan(img, matcher.start(), matcher.end(),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        return builder;
    }



关键点是下面这个类, 思路是调整fontMetrics的属性, 然后控制canvas draw的位置:

import java.lang.ref.WeakReference;

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 android.util.Log;

public class ImageSpanAlignCenter extends ImageSpan {

    private static final char[] ELLIPSIS_NORMAL = { '\u2026' }; // this is "..."
    private static final char[] ELLIPSIS_TWO_DOTS = { '\u2025' }; // this is ".."

    public ImageSpanAlignCenter(Context context, int resourceId) {
        super(context, resourceId);
    }

    public ImageSpanAlignCenter(Drawable d) {
        super(d);
    }

    @Override
    public int getSize(Paint paint, CharSequence text,
                         int start, int end,
                         Paint.FontMetricsInt fm) {
        Drawable d = getCachedDrawable(paint);
        Rect rect = d.getBounds();

        if (fm != null) {
            Paint.FontMetricsInt fontMetrics = new Paint.FontMetricsInt();
            paint.getFontMetricsInt(fontMetrics);

            fm.ascent = fontMetrics.ascent; 
            fm.descent = fontMetrics.descent; 

            fm.top = fontMetrics.top;
            fm.bottom = fontMetrics.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) {
        final String s = text.toString();
        String subS = s.substring(start, end);
        if (ELLIPSIS_NORMAL[0] == subS.charAt(0)
                || ELLIPSIS_TWO_DOTS[0] == subS.charAt(0)) {
            canvas.save();
            canvas.drawText(subS, x, y, paint);
            canvas.restore();
        } else {
            Drawable d = getCachedDrawable(paint);
            canvas.save();
            int transY;
            Paint.FontMetricsInt fontMetrics = new Paint.FontMetricsInt();
            paint.getFontMetricsInt(fontMetrics);
            Rect rect = d.getBounds();

            transY = y + fontMetrics.ascent;

//          Log.v("ImageSpanAlignCenter", "transY=" + transY + " y=" + y + " " + " top=" + top + " bottom=" + bottom
//                    + " rect.bottom=" + rect.bottom + " rect.top=" + rect.top + " " + fontMetrics);
            canvas.translate(x, transY);
            d.draw(canvas);
            canvas.restore();
        }
    }

    private Drawable getCachedDrawable(Paint paint) {
        WeakReference<Drawable> wr = mDrawableRef;
        Drawable d = null;

        if (wr != null)
            d = wr.get();

        if (d == null) {
            d = getDrawable();
            d.setBounds(new Rect(0, 0, paint.getFontMetricsInt(null), paint.getFontMetricsInt(null)));
            mDrawableRef = new WeakReference<Drawable>(d);
        }

        return d;
    }

    private WeakReference<Drawable> mDrawableRef;
}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值