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

Fat*_*tie 84 uikit uiview ios swift

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

CGFloat dashes[] = {4, 2};
[path setLineDash:dashes count:2 phase:0];
[path stroke];
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

有没有办法画出真正的虚线?

在此输入图像描述

有任何想法吗?


由于这个问题很老,没有人提出完整的@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()
    }
}
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

只需在场景中放置一个UIView; 使它成为你想要的任何宽度,这将是虚线的宽度.

只需将课程改为DottedVertical,您就完成了.它将在故事板中正确呈现.

在此输入图像描述

请注意,为块的高度("totalCount"等等)给出的示例代码会使块与像素完美匹配,与创建线的UIView的末端相匹配.

请务必勾选下面的RobMayoff的答案,该答案给出了dot-not-blocks所需的两行代码.

rob*_*off 92

将线帽样式设置为圆形,并将"on"长度设置为一个很小的数字.

斯威夫特操场示例:

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()
Run Code Online (Sandbox Code Playgroud)

结果:

点


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

CGContextSetLineCap(cx, kCGLineCapRound);
Run Code Online (Sandbox Code Playgroud)

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

  • 关键信息在我答案的第一行(英文文本)中.剩下的就是肉汁了. (9认同)
  • 我发现将长度设置为"0.01"会给你一个圆点,而使用"0"时它们会略微拉长. (5认同)
  • 詹姆斯P的建议非常宝贵.这个错误让我感到非常痛苦和工作.谢谢詹姆斯.我会创建一个半答案,这样人们就可以更清楚地看到它. (2认同)

dev*_*eek 14

上面的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();
Run Code Online (Sandbox Code Playgroud)


Ale*_*lex 11

使用与Swift 3.0兼容的UIView扩展,以下应该有效:

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

}
Run Code Online (Sandbox Code Playgroud)

然后,在运行后的功能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)
    }

}
Run Code Online (Sandbox Code Playgroud)


小智 5

大家好,这个解决方案对我很有效。我找到了某个地方并进行了一些更改以防止控制台警告。

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
    }
}
Run Code Online (Sandbox Code Playgroud)

这是结果:

结果