ios - UIView绘制带虚线边框的圆

标签 ios objective-c uiview

有没有办法绘制一个带有虚线边框的 UIView 圆圈?我想控制点之间的间距和点的大小。我尝试指定我自己的图案图像,但是当我把它变成一个圆圈时它看起来不太好:

UIView *mainCircle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
[mainCircle.layer setCornerRadius:100];
[mainCircle.layer setBorderWidth:5.0];
[mainCircle.layer setBorderColor:[[UIColor colorWithPatternImage:[UIImage imageNamed:@"dotted"]] CGColor]];
[self.view addSubview:mainCircle];
[mainCircle setCenter:self.view.center];

enter image description here

最佳答案

aksh1t's answer开始和 rob's answer ,您应该使用圆线帽和破折号图案来执行此操作。

我唯一要补充的是,使用当前代码,您最终可以得到如下结果:

enter image description here

请注意顶部的点是如何重叠的。这是因为圆的周长不能完全被点数整除。

您可以通过之前做一些简单的数学运算相对轻松地解决这个问题。我写了几行代码,允许您提供一个点直径值,以及一个预期的点间距 - 它会尝试近似最近的点间距,这将导致整数个点。

此外,我建议您采用 100% 分层的方法,使用 CAShapeLayer 绘制圆圈。这样您就可以轻松地为其添加动画,而无需为每一帧完全重新绘制它。

像这样应该可以解决问题:

// your dot diameter.
CGFloat dotDiameter = 10.0;

// your 'expected' dot spacing. we'll try to get as closer value to this as possible.
CGFloat expDotSpacing = 20.0;

// the size of your view
CGSize s = self.view.frame.size;

// the radius of your circle, half the width or height (whichever is smaller) with the dot radius subtracted to account for stroking
CGFloat radius = (s.width < s.height) ? s.width*0.5-dotDiameter*0.5 : s.height*0.5-dotDiameter*0.5;

// the circumference of your circle
CGFloat circum = M_PI*radius*2.0;

// the number of dots to draw as given by the circumference divided by the diameter of the dot plus the expected dot spacing.
NSUInteger numberOfDots = round(circum/(dotDiameter+expDotSpacing));

// the calculated dot spacing, as given by the circumference divided by the number of dots, minus the dot diameter.
CGFloat dotSpacing = (circum/numberOfDots)-dotDiameter;

// your shape layer
CAShapeLayer* l = [CAShapeLayer layer];
l.frame = (CGRect){0, 0, s.width, s.height};

// set to the diameter of each dot
l.lineWidth = dotDiameter;

// your stroke color
l.strokeColor = [UIColor blackColor].CGColor;

// the circle path - given the center of the layer as the center and starting at the top of the arc.
UIBezierPath* p = [UIBezierPath bezierPathWithArcCenter:(CGPoint){s.width*0.5, s.height*0.5} radius:radius startAngle:-M_PI*0.5 endAngle:M_PI*1.5 clockwise:YES];
l.path = p.CGPath;

// prevent that layer from filling the area that the path occupies
l.fillColor = [UIColor clearColor].CGColor;

// round shape for your stroke
l.lineCap = kCALineCapRound;

// 0 length for the filled segment (radius calculated from the line width), dot diameter plus the dot spacing for the un-filled section
l.lineDashPattern = @[@(0), @(dotSpacing+dotDiameter)];

[self.view.layer addSublayer:l];

您现在将获得以下输出:

enter image description here

如果您想在 UIView 中使用它,我建议将其子类化并添加 CAShapeLayer 作为子层。您还需要添加一个 mask 层,以便将 View 的内容 mask 到边框内。

我在下面的完整项目中添加了一个示例。


完整项目:https://github.com/hamishknight/Dotted-Circle-View

关于ios - UIView绘制带虚线边框的圆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35961871/

相关文章:

ios - iOS 10 上 UIImageView 顶部 anchor 上的空间更少

iphone - xcode 中的重复 dylib 警告

ios - Core-Plot 选择一个点

ios - 当应用程序终止并在 iOS 中再次启动时,NSNotificationCenter 不会触发

objective-c - 在 Swift 中声明全局宏

iphone - 如何转换相对于特定 View 的窗口坐标?

ios - UIButton 动画不工作

ios - AVPlayerItemDidPlayToEndTimeNotification 在项目未完成播放时发布

ios - 使用 MKMapView 时出现此错误! : "fatal error unexpectedley found nil while unwrapping optional value"

objective-c - iOS 错误 : Assigning to NSMutableString from NSArray object (type 'void' )?