2014-09-24 126 views
70

使用UIKit很容易绘制虚线线条。所以:在2017年使用IBDesignable绘制虚线(不是虚线!)线条

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

enter image description here

有没有什么办法的方式来画一个真正的虚线?

enter image description here

任何想法?


由于这个问题是真的老了,没有人置于满@IBDesignable的解决方案,这是...

希望这样可以节省别人打字。

@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() 
    } 
} 

我把它做成垂直的,你可以很容易地改变。

enter image description here

只要把一个UIView场景;无论你希望的宽度如何,这将是虚线的宽度。

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

enter image description here

注意,对于块(“TOTALCOUNT”等等...)导致完全的块,所述像素的高度给出的示例代码,与所述的UIView的端部匹配的正在创造这条线。

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

+0

这里的画斜线一个很好的方式! :) https://stackoverflow.com/a/45228178/294884 – Fattie 2018-02-13 14:07:27

回答

82

将线条帽样式设置为圆形并将“开”长度设置为很小的数字。

夫特操场例如:

import UIKit 
import PlaygroundSupport 

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] = [0.001, path.lineWidth * 2] 
path.setLineDash(dashes, count: dashes.count, phase: 0) 
path.lineCapStyle = CGLineCap.round 

UIGraphicsBeginImageContextWithOptions(CGSize(width:300, height:20), false, 2) 

UIColor.white.setFill() 
UIGraphicsGetCurrentContext()!.fill(.infinite) 

UIColor.black.setStroke() 
path.stroke() 

let image = UIGraphicsGetImageFromCurrentImageContext() 
let view = UIImageView(image: image) 
PlaygroundPage.current.liveView = view 

UIGraphicsEndImageContext() 

结果:

dots


对于目标-C,用同样的示例类如问题,只需添加

CGContextSetLineCap(cx, kCGLineCapRound); 

之前调用CGContextStrokePath,并更改ra数组值以匹配我的Swift代码。上面的夫特示例的

+8

关键信息是在我的答案的第一个(英文文本)行。其余的是肉汁。 – 2014-10-14 21:16:27

+4

我发现将长度设置为'0.01'会给你一个圆点,而当使用'0'时它们会略微拉长。 – 2016-11-07 10:46:08

+0

我通过拍摄屏幕截图创建了该图像(系统默认快捷方式:⌘⇧4)。 Xcode中从来没有内置的捕获工具,我知道。 – 2016-11-18 18:01:06

13

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(); 
-1

我已经实现下面的代码段,以用虚线样式在titleLabelUILabel)底部viewDidAppear添加边界:

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]; 

Refrence:https://gist.github.com/kaiix/4070967

+0

当我使用您的代码时,这会产生方块,而不是圆圈。 – helloB 2016-06-22 15:58:28

+0

根据您的要求尝试更改moveToPoint,addLineToPoint,linewidth和lineDashPattern值 – iAkki 2016-06-27 05:16:00

+0

不工作,您检查了它吗? – LightNight 2017-03-07 23:57:22

2

我在rob mayoff工作了一下接受的解决方案,很容易定制ze虚线:

  • 更改每个圆的半径。
  • 更改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) 
10

使用UIView的扩展,与雨燕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) 
    } 

} 

然后在之后运行的函数,像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) 
    } 

} 
+1

这会创建一条虚线(即矩形),但是如何创建点线(即圆形)? – Crashalot 2016-12-22 02:41:43

3

好家伙该解决方案罚款为我工作。我找到了某处,并稍微改变了一下以防止控制台警告。

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 
    } 
} 

这是结果:

result

0

在SWIFT 3.1,你可以使用下面的代码:

context.setLineCap(.round) 

有三种样式:

/* Line cap styles. */ 

public enum CGLineCap : Int32 { 

    case butt 

    case round 

    case square 
} 
1

不是完整的答案,只是一个非常重要的疑难杂症,詹姆斯p在对最喜欢的答案评论提出:

他写道:

我发现设置的长度0.01给你一个圆点, ,而使用0时它们会略微伸长。

例如,

let dashes: [CGFloat] = [0.001, path.lineWidth * 2]