使用UIKit绘制虚线线很容易。所以:
CGFloat dashes[] = {4, 2};
[path setLineDash:dashes count:2 phase:0];
[path stroke];
有没有办法画出真正的虚线?
有什么想法吗?
由于这个问题很老,而且没有人提出完整的@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()
}
}
我让它垂直,你可以轻松改变。
只需在场景中放置一个UIView;使它成为你想要的任何宽度,这将是虚线的宽度。
只需将课程更改为DottedVertical
,即可完成。它将在故事板中正确呈现。
请注意,为块的高度(" totalCount"等等...)给出的示例代码会使块完美地与像素匹配,与UIView的末端匹配。创造这条线。
请务必勾选下面的RobMayoff的答案,其中给出了两个不需要块的代码行。
答案 0 :(得分:90)
将线帽样式设置为圆形,并将“on”长度设置为一个很小的数字。
Swift游乐场示例:
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()
结果:
对于objective-C,使用与问题中相同的示例类,只需添加
即可CGContextSetLineCap(cx, kCGLineCapRound);
在调用CGContextStrokePath
之前,并更改ra
数组值以匹配我的Swift代码。
答案 1 :(得分:13)
上面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();
答案 2 :(得分: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)
}
}
然后在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)
}
}
答案 3 :(得分:3)
我在rob mayoff上接受了一些解决方案,可以轻松自定义虚线:
该函数返回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)
答案 4 :(得分: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
}
}
结果如下:
答案 5 :(得分:2)
不是一个完整的答案,只是一个非常重要的问题,James P在最喜欢的答案评论中提出:
他写道:
我发现将长度设置为 0.01 会给你一个圆点, 而使用0时它们会略微拉长。
例如,
let dashes: [CGFloat] = [0.001, path.lineWidth * 2]
答案 6 :(得分:0)
在swift 3.1中,您可以使用以下代码:
context.setLineCap(.round)
有三种风格:
/* Line cap styles. */
public enum CGLineCap : Int32 {
case butt
case round
case square
}
答案 7 :(得分:0)
可以正常使用以下代码,
layer.path = linePath.cgPath
layer.lineWidth = 3
layer.lineDashPattern = [1,layer.lineWidth*2] as [NSNumber]
layer.lineCap = "round"
答案 8 :(得分:0)
嘿,现在回答这个问题可能为时已晚。但是,如果您同意,我想与一个简单的方法分享给将来可能会遇到该问题的开发人员。所以我想这是使用@IBDesignable的最简单解决方案。您只需要创建该类
import UIKit
@IBDesignable class DottedVertical: UIView {
@IBInspectable var dotColor: UIColor = UIColor.red
@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
//DASHED SIMPLE LINE
//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 * 1.1]
path.lineCapStyle = CGLineCap.round
path.setLineDash(dashes, count: dashes.count, phase: 0)
dotColor.setStroke()
path.stroke()
}
}
完成后,请从DottedVertical类的此行let dashes: [CGFloat] = [0.0, itemLength * 1.1]
->第39行中冷自定义图层之间的空间。
或者,如果您想自定义图层的宽度,则只需在情节提要中编辑线视图的宽度即可
答案 9 :(得分:-1)
我已经在titleLabel
中UILabel
(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];