gpt4 book ai didi

ios - UIView坐标系对圆形版UIProgressView的影响

转载 作者:行者123 更新时间:2023-11-29 02:54:53 25 4
gpt4 key购买 nike

我需要一个派生自 UIView 的类,它通过填充越来越大的圆扇区来指示进度(随着进度从 0 到 1,其角度应增长 2 PI)。它就像 UIProgressView 的循环版本。

以下代码还不能完全完成这项工作:它会生成越来越多的小扇区,这些扇区堆叠成闪烁的斑马图案。大概是代码弄乱了它与 UIView flipping 的坐标。它的坐标系,用CGContextAddArc (显然)对“顺时针”等的反直觉定义。

不当行为的原因是什么以及如何解决?

#define PERCENTAGE_TO_RADIANS(PERCENTAGE) ((PERCENTAGE) * 2 * M_PI - M_PI_2)

- (void)drawRect:(CGRect)rect
{
NSAssert(!self.opaque, nil);
NSAssert(!self.clearsContextBeforeDrawing, nil);

CGSize size = self.bounds.size;
CGPoint center = [self.superview convertPoint:self.center toView:self];

NSAssert(size.width == size.height, nil);
NSAssert((self.progress >= 0) && (self.progress <= 1), nil);

NSAssert(PERCENTAGE_TO_RADIANS(0 ) == -M_PI_2 , nil); // 0% progress corresponds to north
NSAssert(PERCENTAGE_TO_RADIANS(0.25) == 0 , nil); // 25% progress corresponds to east
NSAssert(PERCENTAGE_TO_RADIANS(0.5 ) == M_PI_2 , nil); // 50% progress corresponds to south
NSAssert(PERCENTAGE_TO_RADIANS(0.75) == M_PI , nil); // 75% progress corresponds to west
NSAssert(PERCENTAGE_TO_RADIANS(1 ) == 3 * M_PI_2, nil); // 100% progress corresponds to north

CGFloat x = center.x;
CGFloat y = center.y;
CGFloat radius = size.width / 2.0;
CGFloat startAngle = self.lastAngle;
CGFloat endAngle = PERCENTAGE_TO_RADIANS(self.progress);
int clockwise = 0;

if (self.progress > 0) {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);

CGContextSetFillColorWithColor(context, self.sectorTintColor.CGColor);
CGContextSetLineWidth(context, 1);

NSAssert(startAngle <= endAngle, nil);
CGContextMoveToPoint(context, x, y);
CGContextAddArc(context, x, y, radius, startAngle, endAngle, clockwise);
CGContextClosePath(context);

CGContextFillPath(context);

CGContextRestoreGState(context);
}

self.lastAngle = endAngle;
}

最佳答案

您需要知道的最重要的事情是正 Y 向下,这使得角度和顺时针方向不直观。你有两个选择,要么随它去,要么在画任何东西之前翻转 Y 轴。在下面的示例代码中,我采用了后一种方法。

drawRect 方法不累加。换句话说,您需要在每次调用 drawRect 时绘制整个扇区。因此没有理由跟踪起始角度,您应该始终从角度 PI/2 开始并绘制整个扇区。

不需要保存和恢复图形状态。每次调用 drawRect 时都会创建新的图形上下文。

UIColor 类具有 setsetFillsetStroke 方法,允许您在不使用 CGColors 的情况下更改填充和描边颜色。

考虑到所有这些,下面是代码,假设 self.progress 是一个介于 0.0 和 1.0 之间的数字

- (void)drawRect:(CGRect)rect
{
if ( self.progress <= 0 || self.progress > 1.0 )
return;

CGFloat x = self.bounds.size.width / 2.0;
CGFloat y = self.bounds.size.height / 2.0;
CGFloat r = (x <= y) ? x : y;

CGFloat angle = M_PI_2 - self.progress * 2.0 * M_PI;

CGContextRef context = UIGraphicsGetCurrentContext();

// fix the y axis, so that positive y is up
CGContextScaleCTM( context, 1.0, -1.0 );
CGContextTranslateCTM( context, 0, -self.bounds.size.height );

// draw the pie shape
[self.sectorTintColor setFill];
CGContextMoveToPoint( context, x, y );
CGContextAddArc( context, x, y, r, M_PI_2, angle, YES );
CGContextClosePath( context );

CGContextFillPath( context );
}

关于ios - UIView坐标系对圆形版UIProgressView的影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24047199/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com