Android 为什么Canvas::drawArc方法绘制的角度不正确?

Android 为什么Canvas::drawArc方法绘制的角度不正确?,android,canvas,draw,Android,Canvas,Draw,我试图在android视图中绘制一个180°的圆弧。 在onDraw方法中,我使用的Canvas::drawArc如下: canvas.drawArc(arcRect, 180.0f, 180.0f, false, arcBackgroundPaint); 正在使用的油漆有一个strokeCap,类型为BUTT。如下图所示,圆弧的端点看起来不太正确。端部从内径到外径略微向上倾斜 有人知道为什么会这样吗?除了更改传递给drawArc的值以使其实际绘制超过180度之外,还有其他方法修复它吗?这似

我试图在android视图中绘制一个180°的圆弧。 在
onDraw
方法中,我使用的
Canvas::drawArc
如下:

canvas.drawArc(arcRect, 180.0f, 180.0f, false, arcBackgroundPaint);
正在使用的油漆有一个
strokeCap
,类型为
BUTT
。如下图所示,圆弧的端点看起来不太正确。端部从内径到外径略微向上倾斜

有人知道为什么会这样吗?除了更改传递给drawArc的值以使其实际绘制超过180度之外,还有其他方法修复它吗?这似乎是一个我宁愿避免的讨厌的黑客行为

更新: 根据要求,我添加了在圆弧底部绘制直线的代码。我在画弧之前画线,所以线在后面。我还制作了弧形黑色,以便与线条形成更好的对比。结果如下: 恶心

这里有一个为直线和圆弧禁用了抗锯齿的。。。

如果硬件加速打开,则会出现错误角度问题

用真实手机复制(Nexus5,Android 6.0.1)

如何测试:
将android:hardwareAccelerated=“false”添加到AndroidManifest.xml中的应用程序标记中

注意:
文档中没有找到drawArc()支持的第一个API级别,但它的缩放函数来自API17

硬件加速>画布缩放

第一个支持的API级别
简单形状:17
注意:“简单”形状为drawRect()、drawCircle()、drawOval()、drawRoundRect()和drawArc()(useCenter=false)

更新: 正如PICyourBrain在另一个答案中写道的那样,
drawArc()
是出现此问题的部分原因

使用
drawPath()
,不会出现此问题

有关信息:
形状不同,但useCenter=true的
drawArc()
似乎也可以安全使用,因为它不使用硬件加速。(圆弧的末端和中心与直线相连,直线看起来是直的。)

画布缩放(与上面的链接相同)

第一个支持的API级别
复杂形状:x


drawArc()相关的其他Q&A


[旧]
我把这些留给你参考

这是我试过的一些测试结果

更新1-1:

使用emulator Nexus5 API10,使用
arcRect=new RectF(10010015001400)。
对于emulator Nexus5 API16,这种情况不会发生。
(区别在于存在(主机端)硬件加速。)

我认为这似乎是一个与反别名相关的问题,但无论是否设置了setAntiAlias(true)
setDither(true)
,都会发生这种情况

注:这是由于打字错误造成的,对不起。对于该测试,arcRect的纵横比应为1:1。
带有
arcRect=newrectf(10010014001400)
arcPenWidth=200f

使用
arcRect=newrectf(10010015001300)

1-2:用于比较
使用emulator NexusOne(480x800,HDPI)API10,使用
arcRect=new RectF(100100500500)

更新2:线路延长。
我最初认为从视图中绘制可能会导致这种情况,但这也是一个模拟器错误。(不是drawArc()特定的行为。)
如果emulator API10处于横向(水平)方向,则会发生这种情况。
线路位置的计算似乎中断。
请看直线的右端

final float lineStartX = arcRect.left - 250f;
final float lineEndX = arcRect.right + 250f;
仿真器Nexus5 API10

水平(API10)

垂直(API10)

2-2:仅供参考
视图位置(或图形位置)的视图异常行为示例超出范围

更新3:仿真器错误

请查看图像的底部。
蓝线是桌面的背景图像。
仿真器Nexus5 API10

更新4:结果似乎取决于风格。
带有标题栏

没有标题栏

更新5:结果似乎取决于线宽

arcPenWidth=430f(API10,水平面)
右侧可见轻微凹痕。

带440f

450华氏度


这是我的(第一个)测试代码

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

final class TestView extends View
{
    RectF arcRect;
    Paint arcBackgroundPaint;
    Paint linePaint;

    public TestView(final Context context, final AttributeSet attrs)
    {
        super(context, attrs);
        //arcRect = new RectF(100, 100, 500, 500);
        arcRect = new RectF(100, 100, 1500, 1500); // fixed (old: 1500, 1400)
        arcBackgroundPaint = new Paint();
        arcBackgroundPaint.setColor(0xFFFFFFFF);
        arcBackgroundPaint.setStyle(Paint.Style.STROKE);
        arcBackgroundPaint.setStrokeCap(Paint.Cap.BUTT);
        arcBackgroundPaint.setStrokeWidth(200f);
        linePaint = new Paint();
        linePaint.setColor(0xFF00FF00);
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setStrokeCap(Paint.Cap.BUTT);
        linePaint.setStrokeWidth(2f);
    }

    @Override
    protected void onDraw(final Canvas canvas)
    {
        super.onDraw(canvas);
        canvas.drawArc(arcRect, 180.0f, 180.0f, false, arcBackgroundPaint);
        final float lineStartX = arcRect.left - 50f;
        final float lineEndX = arcRect.right + 50f;
        final float lineY = arcRect.centerY();
        canvas.drawLine(lineStartX, lineY, lineEndX, lineY, linePaint);
    }
}

对于其他遇到这种情况的人,我确实找到了解决办法。不要使用
Canvas::drawArc
,而是创建一条路径,向其添加一条弧,然后在画布上绘制路径。像这样:

Path arcPath = new Path();
Rect arcRect = ... // Some rect that will contain the arc
path.addArc(arcRect, 180, 180); 
canvas.drawPath(arcPath, backgroundArcPaint);
然后,高亮显示的渲染问题将不再发生


因为我的问题不是“如何解决问题”,而是“为什么这是一个问题”,所以我没有将此标记为正确答案。

我在相同的设置下进行了测试。但事实并非如此。请在弧的底部添加一条斜线,以检查drawArc()是否是原因。此处相同。我无法重现该问题。@Toris请查看上面我的更新。我已经试过几个操作系统版本和屏幕尺寸。这在任何地方都会发生,但在较小的屏幕上,这种差异显然更为明显。这些图像是在HDPI 480x800的设备上拍摄的。@KalaBalik如果您无法复制这些图像,您介意用
onDraw
中使用的代码(包括您的绘画定义)发布一个答案吗?我想和mind比较一下。@PICyourBrain我已经发布了当前代码。谢谢调查。消除混叠确实会使情况变得更糟,但即使禁用了消除混叠,也会发生这种情况。我以你发布的示例代码为例,将颜色更改为黑色和白色,并将绘制线移到绘制弧上方,同时将绘制线延伸到弧的末端,这变得更加明显。@PICyourBrain我在几个月前遇到了一些奇怪的视图行为,这是由绘制出视图或类似的情况引起的,就我记忆所及,我在一部真正的手机(Nexus6)上运行了示例代码,它看起来与我在上面的原始问题中发布的图像完全一样。所以我想我已经排除了模拟器的错误。我所看到的唯一一张与cor相似的照片