我正在绘制一个自定义View
,它由一个弧线组成,沿着弧线绘制图像。
有点像“财富之轮”截图,其中只有大圆盘的一部分可见,并且当用户拖动视图时,图像变得可见/隐藏在适当的位置和角度沿着光盘的边缘。
这很好用;我使用下面的代码创建一个大的边界框(视图的宽度的四倍,以获得更微妙的弧),我使用Path.arcTo()
来绘制光盘的可见上边缘。
因为边界框是方形的,所绘制的圆弧(如果我要绘制360°)将是圆形的。
// Disc dimensions (based on this View's width/height/padding)
final int radius = width * 2;
final float halfWidth = width / 2f;
final float top = mTopPadding;
// Create a large, square bounding box to draw the disc in.
// Centre horizontally; top edge of the disc == top edge of this View (+ padding)
final RectF discBounds =
new RectF(-radius + halfWidth, top, radius + halfWidth, radius * 2 + top);
// Create an arc along the circumference of the disc,
// but only where it will intersect with this View
double arcSweep = Math.toDegrees(Math.asin(halfWidth / radius)) * 2;
double startAngle = 180 + ((180 - arcSweep) / 2d);
mDiscPath.reset();
mDiscPath.arcTo(discBounds, (float) startAngle, (float) arcSweep);
// Close the shape so that we fill the rest of this View
// (the area underneath the arc) with the disc bg colour
mDiscPath.lineTo(width, height);
mDiscPath.lineTo(0, height);
然后我创建另一个Path
并再次使用完全相同的边界框调用arcTo()
,以便保持相同的圆弧半径。
这次弧的扫掠角度较长,因为View
一次只能显示两个或三个图像,但屏幕外任意数量的图像(在我的情况下,向上)到十点左右。
// Create another arc, along which the images should move,
// based on the number and width of the images.
// We will later use a PathMeasure object created from
// this Path to determine where to draw each image
arcSweep = (mTotalWidth * 180) / (radius * Math.PI);
startAngle = 180 + ((180 - arcSweep) / 2d);
mImagePath.reset();
mImagePath.arcTo(discBounds, (float) startAngle, (float) arcSweep);
在onDraw()
中,mDiscPath
被绘制为背景(canvas.drawPath(mDiscPath, fillPaint)
),然后根据{{1}创建的PathMeasure
对象绘制相应的位图用户拖动了多远。
然而,值得注意的是,当光盘“旋转”时,图像并未精确地遵循预期的路径。这会导致问题,因为图像需要准确对准光盘的边缘。
为了排查故障,我开始使用mImagePath
绘制mImagePath
,以了解为什么图像路径似乎不遵循光盘路径。
在下面的屏幕截图中,为了使问题更加明显,常规位图不会在光盘顶部绘制,canvas.drawPath(mImagePath, strokePaint)
向下翻译4dp(即未翻译时问题也是可见的)。
在这里,我们可以看到自定义视图的三个独立实例堆叠在一起。
但很明显,在每种情况下,黑线(mImagePath
)与彩色圆盘顶部的半径(mImagePath
)不匹配。即,黑弧的半径看起来比盘的半径大。
两个mDiscPath
对象的弧都是使用相同的边界框创建的,所以我希望两个弧的半径相同。
底部光盘上的线条似乎匹配得很好,但前两个光盘显然是错误的 光盘之间唯一真正的区别是显示的图像数量,因此是图像路径的扫描角度(三个视图分别为89°,169°,222°)。
为什么,如果使用完全相同的方形Path
边界框来创建两个RectF
个对象,为什么从这些路径绘制的弧具有不同的半径?
我错过了什么吗?我应该使用不同的API吗?
我确保边界框的大小正确,并且在创建两条路径之间不会发生变化 在所有情况下,起始角和扫掠角看起来都是正确的(即每个弧的中点为270°) 创建全新路径或重置现有路径没有任何区别 对两个路径使用相同的弧扫描确实可以正常工作 我已经在各种设备和方向上进行了测试,无论是否有软件渲染。