我想在文本周围绘制可点击的气泡形状。为了做到这一点,我决定像这样向UIButton添加一个shapelayer:

// Button also has this
bubbleButton.contentEdgeInsets = UIEdgeInsets(top: 5, left: 10, bottom: 5, right: 10)
bubbleButton.setTitle("Gutp", for: .normal)

// In my subclass of UIButton
override func layoutSubviews() {
    super.layoutSubviews()

    self.bubbleLayer?.removeFromSuperlayer()

    let maskLayer = CAShapeLayer.init()
    let bezierPath = UIBezierPath.init(roundedRect: self.bounds,
                                       byRoundingCorners: [.topRight, .topLeft, .bottomLeft],
                                       cornerRadii: CGSize(width: 20, height: 20))
    maskLayer.path = bezierPath.cgPath
    maskLayer.strokeColor = UIColor.red.cgColor
    maskLayer.lineWidth = 2
    maskLayer.fillColor = UIColor.clear.cgColor
    maskLayer.backgroundColor = UIColor.clear.cgColor
    maskLayer.isOpaque = false

    self.bubbleLayer = maskLayer

    if let layers = self.layer.sublayers {
        self.layer.insertSublayer(self.bubbleLayer!, at: UInt32(layers.count))
    } else {
        self.layer.addSublayer(self.bubbleLayer!)
    }
}

请不要看目前的表现。

我有2个这样的按钮添加到UIStackView中。

在某些情况下(通常是短文本),我会得到一个有趣的假象(如果有人可以说的话,会出现一条尾巴),而在文本较长的情况下,我会得到一个正常的气泡:ios - UIButton中的UIBezierPath圆角-LMLPHP

我怎样才能解决这个问题?为什么会出现这种行为?

编辑:在bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:中链接有关brokenradii参数的其他可能相关问题。也许它将帮助遇到类似问题的人。
  • Why is cornerRadii parameter of CGSize type in -[UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:]?
  • Crazy rounded rect UIBezierPath behavior on iOS 7. What is the deal?
  • 最佳答案

    要使用这些圆角的rect方法,必须确保视图尺寸大于所使用的半径。在您的情况下,宽度和高度都必须大于40(半径尺寸为20x20,因此为max(20*2, 20*2) = 40)。

    通常,我更喜欢使用自定义方法来生成此类路径。使用直线和弧线通常可以为您提供更好的灵活性。您可以尝试以下方法:

        /// Returns a path with rounded corners
        ///
        /// - Parameters:
        ///   - frame: A frame at which the path is drawn. To fit in view "bounds" should be used
        ///   - maximumRadius: A maximum corner radius used. For smaller views radius will be min(width/2, height/2)
        /// - Returns: Returns a new path
        func roundedRectPath(inRect frame: CGRect, radiusConstrainedTo maximumRadius: CGFloat) -> UIBezierPath {
    
            let radisu = min(maximumRadius, min(frame.size.width*0.5, frame.size.height*0.5))
    
            let path = UIBezierPath()
    
            path.move(to: CGPoint(x: frame.origin.x + radisu, y: frame.origin.y)) // Top left
            path.addLine(to: CGPoint(x: frame.origin.x + frame.size.width - radisu, y: frame.origin.y))  // Top right
            path.addQuadCurve(to: CGPoint(x: frame.origin.x + frame.size.width, y: frame.origin.y + frame.size.height - radisu), controlPoint: CGPoint(x: frame.origin.x + frame.size.width, y: frame.origin.y)) // Top right arc
            path.addLine(to: CGPoint(x: frame.origin.x + frame.size.width, y: frame.origin.y + frame.size.height - radisu))  // Bottom right
            path.addQuadCurve(to: CGPoint(x: frame.origin.x + frame.size.width - radisu, y: frame.origin.y + frame.size.height), controlPoint: CGPoint(x: frame.origin.x + frame.size.width, y: frame.origin.y + frame.size.height)) // Bottom right arc
            path.addLine(to: CGPoint(x: frame.origin.x + radisu, y: frame.origin.y + frame.size.height))  // Bottom left
            path.addQuadCurve(to: CGPoint(x: frame.origin.x, y: frame.origin.y + frame.size.height - radisu), controlPoint: CGPoint(x: frame.origin.x, y: frame.origin.y + frame.size.height)) // Bottom left arc
            path.addLine(to: CGPoint(x: frame.origin.x, y: frame.origin.y + radisu))  // Top left
            path.addQuadCurve(to: CGPoint(x: frame.origin.x + radisu, y: frame.origin.y), controlPoint: CGPoint(x: frame.origin.x, y: frame.origin.y)) // Top left arc
            path.close()
    
            return path
        }
    

    将其与笔触一起使用时,还需要将边框插入线宽的一半。这是“draw rect”过程的摘录,但可以应用于任何地方:
            UIColor.red.setStroke()
            let lineWidth: CGFloat = 5.0
            let path = roundedRectPath(inRect: bounds.insetBy(dx: lineWidth*0.5, dy: lineWidth*0.5), radiusConstrainedTo: 30.0)
            path.lineWidth = lineWidth
            path.stroke()
    

    注意bounds.insetBy(dx: lineWidth*0.5, dy: lineWidth*0.5)

    关于ios - UIButton中的UIBezierPath圆角,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44905064/

    10-12 00:18
    查看更多