我正在尝试在android视图中绘制180°弧。
在onDraw
方法中,我正在使用Canvas::drawArc
,如下所示:
canvas.drawArc(arcRect, 180.0f, 180.0f, false, arcBackgroundPaint);
正在使用的Paint的strokeCap
类型为BUTT
。正如您在下图中看到的那样,弧的末端看起来不太正确。两端从内径到外径略微倾斜。
有谁知道为什么会这样?有没有办法解决它除了更改传递给drawArc的值,以便它实际绘制超过180度?这似乎是一个讨厌的黑客,我宁愿避免。
更新: 根据要求,我添加了代码以在弧的底部绘制一条直线。我绘制弧线之前画线,所以线条在后面。我还将弧线设为黑色,以便与线条形成更好的对比。结果如下: 呸。
答案 0 :(得分:3)
drawArc如果出现硬件加速,将出现错误的角度问题。
转载真人手机(Nexus 5,Android 6.0.1)。
如何测试:
将android:hardwareAccelerated="false"
添加到AndroidManifest.xml中的应用程序标记。
NB:
在文档中找不到第一个支持的drawArc()API级别,但它的缩放功能来自API17。
硬件加速>画布缩放
https://developer.android.com/guide/topics/graphics/hardware-accel.html
首先支持的API级别
简单形状:17
注意:'简单'形状是drawRect(),drawCircle(),drawOval(),drawRoundRect()和drawArc()(使用useCenter = false)......
更新:
正如PICyourBrain在另一个回答中所写,drawArc()
是出现此问题的部分原因。
使用drawPath()
时,不会出现此问题。
有关信息:
形状不同但使用useCenter = true的drawArc()
似乎也可以安全使用,因为硬件加速不用于它。 (弧的末端和中心与线连接,线看起来笔直。)
Canvas Scaling(上面的相同链接)
首先支持的API级别
复杂形状:x
其他Q&与drawArc()
What's this weird drawArc() / arcTo() bug (graphics glitch) in Android?
[旧]
我会留下这些信息。
以下是我尝试过的一些测试结果。
更新了1-1:
使用模拟器Nexus5 API10,arcRect = new RectF(100, 100, 1500, 1400);
。
使用模拟器Nexus5 API16,这不会发生
(不同之处在于(主机端)硬件加速的存在。)
我认为这似乎是一个与别名相关的问题,但无论arcBackgroundPaint.setAntiAlias(true)
或setDither(true)
是否设置,都会发生这种情况。
注意:这是由错字引起的,抱歉。此测试的arcRect长宽比应为1:1
使用arcRect = new RectF(100, 100, 1400, 1400);
和arcPenWidth = 200f;
使用arcRect = new RectF(100, 100, 1500, 1300);
1-2:用于比较
使用模拟器NexusOne(480x800,HDPI)API10,arcRect = new RectF(100, 100, 500, 500);
更新2:延长线。
我首先想到绘制视图可能会导致这种情况,但这也是一个模拟器错误。 (不是drawArc()特定的行为。)
对于横向(水平)方向的仿真器API10,会发生这种情况
线位置的计算似乎被打破了
请参阅直线的右端。
final float lineStartX = arcRect.left - 250f;
final float lineEndX = arcRect.right + 250f;
2-2:仅供参考 查看视图位置(或绘图位置)的奇怪行为样本超出范围。
更新3:模拟器错误
请参阅图片底部 蓝线是桌面的背景图像 模拟器Nexus5 API10
更新5:结果似乎取决于线宽。
arcPenWidth = 430f(API10,水平)
可以看到右侧有轻微凹口
这是我的(第一个)测试代码。
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);
}
}
答案 1 :(得分:2)
对于遇到此问题的其他人,我确实找到了解决方法。而不是使用Canvas::drawArc
,创建一个路径,向其添加一个弧,然后在画布上绘制路径。像这样:
Path arcPath = new Path();
Rect arcRect = ... // Some rect that will contain the arc
path.addArc(arcRect, 180, 180);
canvas.drawPath(arcPath, backgroundArcPaint);
然后突出显示渲染问题不再出现。
由于我的问题不是"我该如何解决问题"而是"为什么这是一个问题"我并不认为这是正确答案。