画布'drawLine和drawRect不包括结束位置?

jav*_*ian 14 android drawing paint android-canvas

令我惊讶的是,我刚刚发现drawLine和drawRect不包括结束位置,即:

canvas.drawLine(100, 100, 100, 100, paint);
Run Code Online (Sandbox Code Playgroud)

要么

RectF rect = new RectF(100, 100, 100, 100);
canvas.drawRect(rect, paint);
Run Code Online (Sandbox Code Playgroud)

不会画任何东西.

我的油漆定义如下:

Paint paint = new Paint();
paint.setAntiAlias(false);
paint.setStyle(Paint.Style.FILL);
return paint;
Run Code Online (Sandbox Code Playgroud)

我已经尝试将我的绘画定义为FILL_AND_STROKE,但它无济于事.

Android的drawPaint()javadoc甚至没有列出stopX和stopY参数!

所以,如果我想绘制一条完全从beginY到endY(包括)的垂直线,我必须执行以下操作:

canvas.drawLine(constX, beginY, constX, endY + 1)
Run Code Online (Sandbox Code Playgroud)

请注意,我没有将1添加到结束X位置,仅添加到结尾Y(xstays与我想要的垂直线相同).

我的设备是HTC SENSE.

编辑:西蒙,你是对的,而不是问一个问题,我只是试图分享我的惊讶,因为Android在基本的绘图这样的基本情况下没有做文档所说的,并且确保我没有'在我的路上做任何愚蠢的错误.

为了让自己更清楚:drawRect的javadoc说:

public void drawRect(float left,float top,float right,float bottom,Paint paint)

使用指定的绘制绘制指定的Rect.矩形将根据绘画中的样式填充或加框.

left - 要绘制的矩形的左侧

top - 要绘制的矩形的顶边

right - 要绘制的矩形的右侧

bottom - 要绘制的矩形的底边

paint - 用于绘制rect的绘画

所以,写作时

canvas.drawRect(x1, y1, x2, y2)
Run Code Online (Sandbox Code Playgroud)

你期望一个角落在(x1,y1)的矩形; (x1,y2); (x2,y1)和(x2,y2).

Android说:错了!他们将在(x1,y1); (x1,y2-1); (x2-1,y1)和(x2-1,y2-1).

对于好奇的:设置画布剪辑:

canvas.clipRect(x1, y1, x2, y2)
Run Code Online (Sandbox Code Playgroud)

然后尝试画出一点:

canvas.drawPoint(x1, y1, paint);
Run Code Online (Sandbox Code Playgroud)

你在屏幕上得到一个点.

然后尝试在对面的角落:

canvas.drawPoint(x2, y2, paint);
Run Code Online (Sandbox Code Playgroud)

没有出现.其余两个角落也不会出现任何结果:

canvas.drawPoint(x1, y2, paint);


canvas.drawPoint(x2, y2, paint);
Run Code Online (Sandbox Code Playgroud)

对你们来说还不奇怪吗?

因此,结论是Android将右侧底部坐标视为独占,这意味着例如在写入时:

canvas.clipRect(x1, y1, x2, y2)
Run Code Online (Sandbox Code Playgroud)

您将获得(x1,y1,x2 - 1,y2 - 1)的剪切边界.这同样与每一个需要方法正确底部坐标或矩形/ RectF对象.

Har*_*ger 5

您的问题显示Android的绘图API不一致.你说

所以,如果我想绘制一条完全从beginY到endY(包括)的垂直线,我必须执行以下操作:

canvas.drawLine(constX, beginY, constX, endY + 1)
Run Code Online (Sandbox Code Playgroud)

请注意,我没有将1添加到结束X位置,仅添加到结尾Y(xstays与我想要的垂直线相同).

括号中的句子在我看来是理解不一致性质的关键:

您还可以将1添加到结束X位置(或甚至添加到起始X位置!),您将获得与像素相同的完全相同的行.这是为什么?因为从Android的"左像素输入/右像素输出" - 从概念转换为"开始和结束像素输入" - 概念的基础算法如下所示(仅针对x显示,对于y,它是相同的):

int left, top, right, bottom; // left/top pixel inclusive, right/bottom pixel exclusive
int x1, y1, x2, y2;           // x1/y1 and x2/y2 pixels inclusive

if ( left == right ) {
    x1 = x2 = left;
} else if ( left < right ) {
    x1 = left;
    x2 = right - 1;
} else {
    x1 = right;
    x2 = left - 1;
}
Run Code Online (Sandbox Code Playgroud)

这个(在我看来次优)转换的结果是该行

canvas.drawLine(150, 150, 149, 160, paint);
Run Code Online (Sandbox Code Playgroud)

与...完全平行

canvas.drawLine(150, 150, 151, 160, paint);
Run Code Online (Sandbox Code Playgroud)

我想每个人都会期望反V型,因为端点之间至少有1个像素(它们的距离是两个像素)并且起始点是相同的.

但是在各种设备和Android版本上进行了测试,第一条完美垂直线在像素列149中,第二列在第150列中.

BTW:正确的转换使用"开始和结束像素" - 概念是:

int x1, y1, x2, y2;           // x1/y1 and x2/y2 pixels inclusive

if ( x1 <= x2 )
    ++x2;
else
    ++x1;
if ( y1 <= y2 )
    ++y2;
else
    ++y1;
canvas.drawLine(x1, y1, x2, y2, paint);
Run Code Online (Sandbox Code Playgroud)