You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Canvas的Bitmap(Drawable XML)内部显示文本?

解决Canvas中文字显示在Bitmap圆形内部的问题

嘿,我明白你的困扰了!你现在是先把圆形Drawable转成Bitmap,然后用canvas.drawBitmap()画出来,再用drawText()加文字,但文字跑到Bitmap上面去了对吧?这是因为你没把文字的绘制坐标和Bitmap的位置、尺寸对齐,而且文字的基线绘制特性也会影响位置。咱们一步步来搞定它:

方法一:调整文字坐标,让它居中在Bitmap内部

1. 明确Bitmap的位置和尺寸

先把你绘制Bitmap时的坐标和它的宽高存下来,方便后续计算:

// 假设你绘制Bitmap的起始坐标
float bitmapLeft = 150f;
float bitmapTop = 150f;
// 获取Bitmap的宽高
int bitmapWidth = yourCircleBitmap.getWidth();
int bitmapHeight = yourCircleBitmap.getHeight();

2. 配置文字Paint并计算文字尺寸

设置文字的样式,然后获取文字的边界,这样才能准确计算居中位置:

Paint textPaint = new Paint();
textPaint.setTextSize(28f); // 根据你的圆形大小调整文字尺寸
textPaint.setColor(Color.WHITE); // 选个和圆形对比明显的颜色
textPaint.setTextAlign(Paint.Align.CENTER); // 设置文字居中对齐,简化X坐标计算
textPaint.setAntiAlias(true); // 让文字更平滑

String targetText = "5"; // 你要显示的文字
Rect textBounds = new Rect();
textPaint.getTextBounds(targetText, 0, targetText.length(), textBounds);
int textHeight = textBounds.height();

3. 计算文字的绘制坐标并绘制

关键是让文字在圆形Bitmap的中心:

  • X坐标:Bitmap的中心X,也就是bitmapLeft + bitmapWidth / 2f(因为我们设置了Align.CENTER,文字会以这个点为中心左右对齐)
  • Y坐标:Bitmap的中心Y加上文字高度的一半,因为文字的基线默认在下方,这样调整后文字能垂直居中

然后记住先画Bitmap,再画文字,这样文字才会覆盖在Bitmap内部:

// 先绘制圆形Bitmap
canvas.drawBitmap(yourCircleBitmap, bitmapLeft, bitmapTop, null);
// 再绘制文字到Bitmap中心
float textX = bitmapLeft + bitmapWidth / 2f;
float textY = bitmapTop + bitmapHeight / 2f + textHeight / 2f;
canvas.drawText(targetText, textX, textY, textPaint);

方法二:自定义Drawable,让圆形和文字成为一体

如果你的圆形是固定样式的,直接自定义一个Drawable,把圆形和文字一起画,这样就不用分开处理Bitmap和文字了,更省心:

public class TextCircleDrawable extends Drawable {
    private final Paint circlePaint;
    private final Paint textPaint;
    private final String displayText;

    public TextCircleDrawable(String text) {
        this.displayText = text;
        
        // 初始化圆形画笔
        circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        circlePaint.setColor(Color.parseColor("#2196F3")); // 圆形颜色
        
        // 初始化文字画笔
        textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(Color.WHITE);
        textPaint.setTextSize(32f);
        textPaint.setTextAlign(Paint.Align.CENTER);
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        Rect drawBounds = getBounds();
        // 绘制圆形(以Drawable的边界为基准画正圆)
        float circleRadius = Math.min(drawBounds.width(), drawBounds.height()) / 2f;
        canvas.drawCircle(drawBounds.centerX(), drawBounds.centerY(), circleRadius, circlePaint);
        
        // 绘制文字到圆形中心
        Rect textBounds = new Rect();
        textPaint.getTextBounds(displayText, 0, displayText.length(), textBounds);
        float textY = drawBounds.centerY() + textBounds.height() / 2f;
        canvas.drawText(displayText, drawBounds.centerX(), textY, textPaint);
    }

    @Override
    public void setAlpha(int alpha) {
        circlePaint.setAlpha(alpha);
        textPaint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) {
        circlePaint.setColorFilter(colorFilter);
        textPaint.setColorFilter(colorFilter);
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }
}

使用的时候,你可以直接把这个Drawable转成Bitmap,或者直接调用它的draw()方法绘制到Canvas上,这样圆形和文字就是一个整体,不会出现位置偏移的问题。


内容的提问来源于stack exchange,提问作者Soumya Priya Nayak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:51:04