java - 如何用起始文本绘制圆弧

标签 java android kotlin canvas

我必须使用 Canvas 创建一个圆弧并在圆弧的起始位置添加文本,但它看起来不正确。请看图片,我的文字被剪掉了顶部位置,我的文字显示为线性而不是曲线。

enter image description here

我的代码

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mRect == null) {
            centerX = getMeasuredWidth() / 2;
            centerY = getMeasuredHeight() / 2;
            radius = Math.min(centerX, centerY);
            int startTop = STROKE_WIDTH / 2;
            mRect = new RectF(STROKE_WIDTH / 2, STROKE_WIDTH / 2, (2 * radius - startTop), (2 * radius - startTop));
            canvas.drawArc(mRect, 270, 270, false, mDegreesPaint);

            Paint paint = new Paint();

            paint.setColor(Color.TRANSPARENT);
            paint.setAntiAlias(true);
            paint.setStyle(Paint.Style.FILL_AND_STROKE);
            paint.setTextAlign(Paint.Align.LEFT);
            paint.setLinearText(true);
            canvas.drawPaint(paint);

            paint.setColor(getResources().getColor(R.color.colorPrimaryDark));
            paint.setTextSize(30);

            //float radius = 300;
                float x = (float)(radius * Math.cos(mRect.width() * Math.PI)) + getWidth()/2 - 10;
                float y = (float)(radius * Math.sin(mRect.height() * Math.PI )) + getHeight()/2 - 20;

            Path addArc = new Path();
            addArc.arcTo(mRect, 250, 270);

            canvas.drawTextOnPath("text",addArc, 0, 0 , paint);




        }
    }

最佳答案

如果 View 被重绘,if (mRect == null) 行会让你陷入困境。它会变成空白。您应该在其声明处实例化矩形并在 onDraw() 中修改其尺寸。我还会在绘制方法之外设置您的绘制,以便在必须在动画中重绘此 View 时使其速度更快。

我不确定您的代码中的 xy 的用途,但无论您计算什么,很可能都没有意义,因为您的三角函数内有高度和宽度。

因此,您可以通过减去矩形笔划宽度的一半来在矩形内绘制圆弧。然后,您使用同一个矩形来制作供文本放置的圆弧。文本在其基线处绘制(字母的底部,不像 g、j、p 和 y 那样下垂)。

因此,在您的情况下,您可能希望文本适合 View 边界内,因此您应该制作一个比 View 小文本大小的圆弧,而不是用于圆弧的笔画宽度的一半。

我还发现如何放置圆弧矩形存在错误。它位于 View 的左下角。因此,如果您的 View 不是方形的,它将偏离中心。您应该根据中心点进行定位。

由于您执行了两次此计算,因此您可以为其编写一个函数。

private val mRect = RectF()
private val mTextPaint = Paint().apply {
    color = resources.getColor(R.color.colorPrimaryDark)
    antiAlias = true
    style = Paint.Style.FILL_AND_STROKE
    textAlign = Paint.Align.LEFT
    linearText = true
}

private fun updateCenteredRect(rect: RectF, inset: Int) {
    val centerX = measuredWidth / 2
    val centerY = measuredHeight / 2
    val radius = min(centerX, centerY) - inset
    rect.set(centerX - radius, centerY - radius, radius * 2, radius * 2)
}

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    updateCenteredRect(mRect, STROKE_WIDTH / 2)
    canvas.drawArc(mRect, 270, 270, false, mDegreesPaint)

    val textSize = 30 // You should calculate this based on screen density or it will look too big or small on some devices
    mTextPaint.textSize = textSize
    updateCenteredRect(mRect, textSize)
    Path addArc = new Path().apply {
        arcTo(mRect, 250, 270)
    }
    canvas.drawTextOnPath("text", addArc, 0, 0, mTextPaint)
}

我写这篇文章时并没有真正注意到你的原始代码是用 Java 编写的。我通过 Kotlin 标签找到了你的问题。

关于java - 如何用起始文本绘制圆弧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60189624/

相关文章:

android - 延迟线程也卡住其他 Activity

java - 将相机图像保存到 SD 卡,检索并上传到 Firestore 存储

java - 有没有办法捕获Hibernate和Ibatis中执行的SQL语句然后将它们保存到数据库中?

java - Quarkus PanacheEntity 在测试期间未保存

android - 显示 Android 堆栈

kotlin - java.lang.IllegalStateException : Could not find sun. Misc.Unsafe 而@MockK

android - 无法检查已删除类型的实例 : List<Occupation_Info>

java - Schedulers.newElastic 和 Schedulers.elastic 方法有什么区别?

java - 确定打开了多少顶级容器

android - 我如何使用 Firebase Storage 存储到不同的存储桶