【问题标题】:circle with dash lines uiview带有虚线的圆圈 uiview
【发布时间】:2019-05-28 15:58:56
【问题描述】:

我正在尝试用虚线画一个圆圈。我可以在矩形中制作线条,但我不知道如何在圆形中制作这些线条。这是我得到的答案,但它在 Objective-C 中:UIView Draw Circle with Dotted Line Border

这是我的代码,它用虚线制作了一个矩形。

func addDashedBorder() {
    let color = UIColor.red.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 = color
    shapeLayer.lineWidth = 2
    shapeLayer.lineJoin = CAShapeLayerLineJoin.round
    shapeLayer.lineDashPattern = [6,3]
    shapeLayer.path = UIBezierPath(roundedRect: shapeRect, cornerRadius: 5).cgPath

    self.layer.addSublayer(shapeLayer)
}

【问题讨论】:

  • 您是否尝试使用您的确切代码,但将UIBezierPath 调用更改为创建一个圆而不是圆角矩形?

标签: ios swift uiview


【解决方案1】:

当然,您可以使用选定的破折号图案渲染您的圆形 UIBezierPath

class DashedCircleView: UIView {
    private var shapeLayer: CAShapeLayer = {
        let shapeLayer = CAShapeLayer()
        shapeLayer.strokeColor = UIColor.red.cgColor
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.lineWidth = 10
        shapeLayer.lineCap = .round
        shapeLayer.lineDashPattern = [20, 60]
        return shapeLayer
    }()

    override init(frame: CGRect = .zero) {
        super.init(frame: frame)
        configure()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        configure()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        updatePath()
    }
}

private extension DashedCircleView {
    func configure() {
        layer.addSublayer(shapeLayer)
    }

    func updatePath() {
        let rect = bounds.insetBy(dx: shapeLayer.lineWidth / 2, dy: shapeLayer.lineWidth / 2)
        let radius = min(rect.width, rect.height) / 2
        let center = CGPoint(x: rect.midX, y: rect.midY)
        let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: .pi * 2, clockwise: true)
        shapeLayer.path = path.cgPath
    }
}

产生:

这种方法的问题是很难让虚线图案对齐(请注意“3 点钟”位置的尴尬虚线)。您可以通过确保lineDashPattern 的两个值相加等于某个数字来解决这个问题,该数字均匀地划分为圆的周长(例如 2π × 半径):

let circumference: CGFloat = 2 * .pi * radius
let count = 30
let relativeDashLength: CGFloat = 0.25
let dashLength = circumference / CGFloat(count)
shapeLayer.lineDashPattern = [dashLength * relativeDashLength, dashLength * (1 - relativeDashLength)] as [NSNumber]

或者,您可以完全不使用lineDashPattern,而是保留一个实心笔划,并将path 本身制作为一系列小弧线。这样我可以实现所需的虚线效果,但要确保它在我们从 0 旋转到 2π 时均匀地分成count 小弧:

class DashedCircleView: UIView {
    private var shapeLayer: CAShapeLayer = {
        let shapeLayer = CAShapeLayer()
        shapeLayer.strokeColor = UIColor.red.cgColor
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.lineWidth = 10
        shapeLayer.lineCap = .round
        return shapeLayer
    }()

    override init(frame: CGRect = .zero) {
        super.init(frame: frame)
        configure()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        configure()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        updatePath()
    }
}

private extension DashedCircleView {
    func configure() {
        layer.addSublayer(shapeLayer)
    }

    func updatePath() {
        let rect = bounds.insetBy(dx: shapeLayer.lineWidth / 2, dy: shapeLayer.lineWidth / 2)
        let radius = min(rect.width, rect.height) / 2
        let center = CGPoint(x: rect.midX, y: rect.midY)

        let path = UIBezierPath()
        let count = 30
        let relativeDashLength: CGFloat = 0.25 // a value between 0 and 1
        let increment: CGFloat = .pi * 2 / CGFloat(count)

        for i in 0 ..< count {
            let startAngle = increment * CGFloat(i)
            let endAngle = startAngle + relativeDashLength * increment
            path.move(to: CGPoint(x: center.x + radius * cos(startAngle), 
                                  y: center.y + radius * sin(startAngle)))
            path.addArc(withCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
        } 
        shapeLayer.path = path.cgPath
    }
}

产生:

【讨论】:

  • 当我把图片放在这个圈子里时,这个圈子没有设置约束
  • 我建议使用视图调试器并确认圆形视图和图像视图的框架,看看是否有一个或多个框架错误的问题(即你没有正确设置约束)或圆形视图的CAShapeLayer 是否错误(例如,您没有像我上面那样更新layoutSubviewsviewDidLayoutSubviews 中的形状层)。一旦您确定了这两个问题中的哪一个问题,您就可以随时发布一个新的、单独的问题以及您的发现。
【解决方案2】:

您可以使用UIBezierPath(ovalIn:) 在方形视图中创建圆形路径。

extension UIView {
    func addDashedCircle() {
        let circleLayer = CAShapeLayer()
        circleLayer.path = UIBezierPath(ovalIn: bounds).cgPath
        circleLayer.lineWidth = 2.0
        circleLayer.strokeColor =  UIColor.red.cgColor//border of circle
        circleLayer.fillColor = UIColor.white.cgColor//inside the circle
        circleLayer.lineJoin = .round
        circleLayer.lineDashPattern = [6,3]
        layer.addSublayer(circleLayer)
    }
}

设置视图背景颜色 .clear 和图层填充颜色 .white

class View1: UIViewController {
    @IBOutlet weak var circleView: UIView!
    override func viewDidLoad() {
        super.viewDidLoad()
        circleView.backgroundColor = .clear//outside the circle
        circleView.addDashedCircle()
    }
}

或使用UIBezierPath(arcCenter:radius:startAngle:endAngle:clockwise:)

circleLayer.path = UIBezierPath(arcCenter: CGPoint(x: frame.size.width/2, y: frame.size.height/2),
                            radius: min(frame.size.height,frame.size.width)/2,
                            startAngle: 0,
                            endAngle: .pi * 2,
                            clockwise: true).cgPath

【讨论】:

  • 如何去掉两边的白色,在圆圈下面应该是白色的?
  • 是的,我现在做到了,我想在破折号之间做更多的间隔
  • 好的,通过 circleLayer.lineDashPattern = [6,6] 做到了,非常感谢你
  • @ShahzadAli 使用circleLayer.lineDashPattern = [10,15]。这里 10 是红线的长度,15 是红线之间的空白长度
  • 兄弟,当我给出纵横比时,我必须做一件事,圆圈有问题
【解决方案3】:

使用UIBezierPath的圆形路径变体绘制路径

shapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: frame.size.width * 0.5, y: frame.size.height * 0.5), radius: frame.size.width * 0.5, startAngle: 0, endAngle: .pi * 2, clockwise: true)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-17
    • 1970-01-01
    相关资源
    最近更新 更多