在2017年用IBDesignable绘制虚线(而不是虚线)

用UIKit绘制虚线很容易。 所以:

CGFloat dashes[] = {4, 2}; [path setLineDash:dashes count:2 phase:0]; [path stroke]; 

在这里输入图像描述

有没有办法绘制一条真正的虚线?

在这里输入图像描述

有任何想法吗?


由于这个问题是真的老了,没有人提出了一个完整的@IBDesignable解决scheme,这里是…

希望它可以帮助某些人打字。

 @IBDesignable class DottedVertical: UIView { @IBInspectable var dotColor: UIColor = UIColor.etc @IBInspectable var lowerHalfOnly: Bool = false override func draw(_ rect: CGRect) { // say you want 8 dots, with perfect fenceposting: let totalCount = 8 + 8 - 1 let fullHeight = bounds.size.height let width = bounds.size.width let itemLength = fullHeight / CGFloat(totalCount) let path = UIBezierPath() let beginFromTop = CGFloat(0.0) let top = CGPoint(x: width/2, y: beginFromTop) let bottom = CGPoint(x: width/2, y: fullHeight) path.move(to: top) path.addLine(to: bottom) path.lineWidth = width let dashes: [CGFloat] = [itemLength, itemLength] path.setLineDash(dashes, count: dashes.count, phase: 0) // for ROUNDED dots, simply change to.... //let dashes: [CGFloat] = [0.0, itemLength * 2.0] //path.lineCapStyle = CGLineCap.round dotColor.setStroke() path.stroke() } } 

我做了垂直,你可以很容易地改变。

在这里输入图像描述

只要在场景中放置一个UIView; 使其无论你希望的宽度,这将是虚线的宽度。

只需将该类更改为DottedVertical ,即可完成。 它将在故事板中正确渲染。

在这里输入图像描述

请注意,为块的高度(“totalCount”等)给出的示例代码完美地导致块的像素,与创build线的UIView的末端相匹配。

一定要勾选RobMayoff的答案,它给出了点不是块的两个必要的代码行。

将线条帽样式设置为圆形,并将“开”长度设置为零。

Swift游乐场的例子:

 import UIKit import XCPlayground let path = UIBezierPath() path.move(to: CGPoint(x:10,y:10)) path.addLine(to: CGPoint(x:290,y:10)) path.lineWidth = 8 let dashes: [CGFloat] = [path.lineWidth * 0, path.lineWidth * 2] path.setLineDash(dashes, count: dashes.count, phase: 0) path.lineCapStyle = CGLineCap.round UIGraphicsBeginImageContextWithOptions(CGSize(width:300, height:20), false, 2) path.stroke() XCPlaygroundPage.currentPage.captureValue(UIGraphicsGetImageFromCurrentImageContext(), withIdentifier: "image") UIGraphicsEndImageContext() 

结果:

点


对于Objective-C,使用与问题中相同的示例类,只需添加

 CGContextSetLineCap(cx, kCGLineCapRound); 

之前调用CGContextStrokePath ,并更改ra数组值以匹配我的Swift代码。

上面的Swift示例的Objective-C版本:

 UIBezierPath * path = [[UIBezierPath alloc] init]; [path moveToPoint:CGPointMake(10.0, 10.0)]; [path addLineToPoint:CGPointMake(290.0, 10.0)]; [path setLineWidth:8.0]; CGFloat dashes[] = { path.lineWidth, path.lineWidth * 2 }; [path setLineDash:dashes count:2 phase:0]; [path setLineCapStyle:kCGLineCapRound]; UIGraphicsBeginImageContextWithOptions(CGSizeMake(300, 20), false, 2); [path stroke]; UIImage * image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); 

使用一个UIView扩展,与Swift 3.0兼容,以下应该工作:

 extension UIView { func addDashedBorder(strokeColor: UIColor, lineWidth: CGFloat) { self.layoutIfNeeded() let strokeColor = strokeColor.cgColor let shapeLayer:CAShapeLayer = CAShapeLayer() let frameSize = self.frame.size let shapeRect = CGRect(x: 0, y: 0, width: frameSize.width, height: frameSize.height) shapeLayer.bounds = shapeRect shapeLayer.position = CGPoint(x: frameSize.width/2, y: frameSize.height/2) shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.strokeColor = strokeColor shapeLayer.lineWidth = lineWidth shapeLayer.lineJoin = kCALineJoinRound shapeLayer.lineDashPattern = [5,5] // adjust to your liking shapeLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: shapeRect.width, height: shapeRect.height), cornerRadius: self.layer.cornerRadius).cgPath self.layer.addSublayer(shapeLayer) } } 

然后,在viewDidLoad之后运行的函数(如viewDidLayoutSubviews ,在相关视图上运行addDashedBorder函数:

 class ViewController: UIViewController { var someView: UIView! override func viewDidLoad() { super.viewDidLoad() someView = UIView() someView.layer.cornerRadius = 5.0 view.addSubview(someView) someView.translatesAutoresizingMaskIntoConstraints = false someView.widthAnchor.constraint(equalToConstant: 200).isActive = true someView.heightAnchor.constraint(equalToConstant: 200).isActive = true someView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true someView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true } override func viewDidLayoutSubviews() { someView.addDashedBorder(strokeColor: UIColor.red, lineWidth: 1.0) } } 

我工作了一下rob mayoff接受的解决scheme,轻松定制虚线:

  • 改变每个圆的半径。
  • 更改2个圆圈之间的空格数目。
  • 更改要生成的模式的数量。

该函数返回一个UIImage:

 extension UIImage { class func dottedLine(radius radius: CGFloat, space: CGFloat, numberOfPattern: CGFloat) -> UIImage { let path = UIBezierPath() path.moveToPoint(CGPointMake(radius/2, radius/2)) path.addLineToPoint(CGPointMake((numberOfPattern)*(space+1)*radius, radius/2)) path.lineWidth = radius let dashes: [CGFloat] = [path.lineWidth * 0, path.lineWidth * (space+1)] path.setLineDash(dashes, count: dashes.count, phase: 0) path.lineCapStyle = CGLineCap.Round UIGraphicsBeginImageContextWithOptions(CGSizeMake((numberOfPattern)*(space+1)*radius, radius), false, 1) UIColor.whiteColor().setStroke() path.stroke() let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image } } 

这里是如何获得图像:

 UIImage.dottedLine(radius: 100, space: 2, numberOfPattern: 1) 

大家好这个解决scheme为我工作得很好。 我find了一些地方,并改变了一点,以防止控制台警告。

 extension UIImage { static func drawDottedImage(width: CGFloat, height: CGFloat, color: UIColor) -> UIImage { let path = UIBezierPath() path.move(to: CGPoint(x: 1.0, y: 1.0)) path.addLine(to: CGPoint(x: width, y: 1)) path.lineWidth = 1.5 let dashes: [CGFloat] = [path.lineWidth, path.lineWidth * 5] path.setLineDash(dashes, count: 2, phase: 0) path.lineCapStyle = .butt UIGraphicsBeginImageContextWithOptions(CGSize(width: width, height: height), false, 2) color.setStroke() path.stroke() let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return image } } 

这是结果:

结果

在swift 3.1中你可以使用下面的代码:

 context.setLineCap(.round) 

有三种风格:

  /* Line cap styles. */ public enum CGLineCap : Int32 { case butt case round case square } 

我已经实现了下面的一段代码,在viewDidAppeartitleLabelUILabel )的底部添加了带虚线样式的边框:

 CAShapeLayer *shapelayer = [CAShapeLayer layer]; UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(0.0, titileLabel.frame.size.height-2)]; [path addLineToPoint:CGPointMake(SCREEN_WIDTH, titileLabel.frame.size.height-2)]; UIColor *fill = [UIColor colorWithRed:0.80f green:0.80f blue:0.80f alpha:1.00f]; shapelayer.strokeStart = 0.0; shapelayer.strokeColor = fill.CGColor; shapelayer.lineWidth = 2.0; shapelayer.lineJoin = kCALineJoinRound; shapelayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:2],[NSNumber numberWithInt:3 ], nil]; shapelayer.path = path.CGPath; [titileLabel.layer addSublayer:shapelayer]; 

参考: https : //gist.github.com/kaiix/4070967