UIView 用虚线边框画圆

Posted

技术标签:

【中文标题】UIView 用虚线边框画圆【英文标题】:UIView Draw Circle with Dotted Line Border 【发布时间】:2016-03-12 18:46:56 【问题描述】:

有没有办法画一个带有虚线边框的 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];

【问题讨论】:

【参考方案1】:

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

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

请注意,在顶部,您会得到重叠的点。这是因为圆的周长不能完全被点数整除。

您可以通过之前做一些简单的数学运算来相对轻松地解决这个问题。我编写了几行代码,可让您提供点直径值以及预期的点间距 - 它会尝试逼近最接近的点间距,从而产生整数个点。

另外,我建议您采用 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];

您现在将获得以下输出:

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

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


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

【讨论】:

如果您必须为它们设置动画,这里有一个有用的提示! ***.com/a/45787919/294884 嗨,谢谢,这很有用,但是如何点到圆的中心。这里是弧的顶部。但我想要一些弧的下方 @Hamish 我怎样才能减少两个点之间的差距。有什么想法吗?【参考方案2】:

最好的方法是画一个圆圈UIBezierPath,并将路径设置为虚线样式。点式路径代码取自this answer。

UIBezierPath * path = [[UIBezierPath alloc] init];
[path addArcWithCenter:center radius:50 startAngle:0 endAngle:2 * M_PI clockwise:YES];
[path setLineWidth:8.0];
CGFloat dashes[] =  path.lineWidth, path.lineWidth * 2 ;
[path setLineDash:dashes count:2 phase:0];
[path setLineCapStyle:kCGLineCapRound];

// After you have the path itself, you can either make 
// an image and set it in a view or use the path directly
// in the layer of the view you want to.
// This is the code for the image option.

UIGraphicsBeginImageContextWithOptions(CGSizeMake(300, 20), false, 2);
[path stroke];
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

【讨论】:

以上是关于UIView 用虚线边框画圆的主要内容,如果未能解决你的问题,请参考以下文章

去除图片链接边框及其链接虚线

74shape 画圆 加 边框

在HTML中 怎么去掉点击select时的虚线边框,求大神指点下?

css定义的边框虚线在火狐中不显示?

IE兼容~a标签点击有虚线边框的问题

jqgrid 在拖动列时 能不能不显示 列的边框 虚线?