【问题标题】:Round Top Corners of a UIButton in SwiftSwift 中 UIButton 的圆顶角
【发布时间】:2016-09-06 22:14:03
【问题描述】:

我知道我可以使用以下方法绕过所有四个角:

 myBtn.layer.cornerRadius = 8
 myBtn.layer.masksToBounds = true

由于我只想第二轮,所以我做了一些研究,发现this

extension UIView {
    func roundCorners(corners:UIRectCorner, radius: CGFloat) {
        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.CGPath
        self.layer.mask = mask
    }
}

这样称呼:

view.roundCorners([.TopLeft , .TopRight], radius: 10)

但这不适用于 UIButton。当我将扩展名切换为 UIButton 类型并将其传递给 button 时,输出如下所示:

问题是,如何调整它以在 UIButton 上工作?

【问题讨论】:

  • 请考虑接受我的回答,因为这是对问题最准确的回答。这个问题的未来访问者不会仅仅因为看到一堆有效的代码而感到满意,但并没有解释它为什么有效(这就是当前接受的答案所做的),而是通过看到 where 问题所在– 我的回答已经确定了这一点。
  • 在这里查看我的答案:stackoverflow.com/a/40222533/2594699

标签: ios swift uibutton rounded-corners


【解决方案1】:

这对我有帮助

extension UIView {

   func roundCorners(
      corners: UIRectCorner, 
      radius: CGFloat
   ) {
      let path = UIBezierPath(
         roundedRect: bounds,
         byRoundingCorners: corners,
         cornerRadii: CGSize(
            width: radius, 
            height: radius
         )
      )

      let mask = CAShapeLayer()
      mask.path = path.cgPath
      layer.mask = mask
   }
}

请注意,如果您附加了布局约束,则必须在 UIView 子类中按如下方式刷新它:

override func viewDidLayoutSubviews() {
   super.viewDidLayoutSubviews()

   yourButtonOutletName.roundCorners(
      corners: [.topLeft, .topRight],
      radius: yourButtonOutletName.frame.height / 2
   )
}

【讨论】:

    【解决方案2】:

    圆角应用于 view/Button .. 的角,但来到 button 的边框,它没有正确应用。我有什么解决办法吗? @

    这是我使用的代码,它在 iOS11.0 及更高版本中有效(边框),而不是在以下版本中(

    if #available(iOS 11.0, *) {
            self.layer.cornerRadius = radius
            self.layer.maskedCorners = maskedCorners
        } else {
            let shapeLayer = CAShapeLayer()
            shapeLayer.position = self.center
            self.layer.masksToBounds = true
            self.clipsToBounds = true
            let bezirePath = UIBezierPath(roundedRect: self.bounds,
                                          byRoundingCorners: corners,
                                          cornerRadii: CGSize(width: radius, height: radius))
            shapeLayer.bounds = frame
            shapeLayer.path = bezirePath.cgPath
    
            self.layer.mask = shapeLayer
    

    【讨论】:

    • 请将此作为一个新问题提出。
    • 在调整按钮大小时,使用这样的框架将不起作用。例如将按钮添加到 UIStackView。
    【解决方案3】:

    对于 swift 5 和最大的灵活性

    使用 roundCorners 函数定义扩展

    extension UIButton {
        func roundCorners(corners: UIRectCorner, radius: Int = 8) {
            let maskPath1 = UIBezierPath(roundedRect: bounds,
                                         byRoundingCorners: corners,
                                         cornerRadii: CGSize(width: radius, height: radius))
            let maskLayer1 = CAShapeLayer()
            maskLayer1.frame = bounds
            maskLayer1.path = maskPath1.cgPath
            layer.mask = maskLayer1
        }
    }
    

    调用roundCorners函数

    myButton.roundCorners(corners: [.topLeft, .topRight])
    

    或具有特定半径

    myButton.roundCorners(corners: [.topLeft, .topRight], radius: 20)
    

    【讨论】:

    • 如何使用 [.topLeft , .topRight] 为这些按钮设置阴影?
    • 在调整按钮大小时,使用这样的框架将不起作用。例如将按钮添加到 UIStackView。
    【解决方案4】:

    添加 UIButton 的扩展:

    extension UIButton{
        func roundedButton(){
            let maskPath1 = UIBezierPath(roundedRect: bounds,
                byRoundingCorners: [.topLeft , .topRight],
                cornerRadii: CGSize(width: 8, height: 8))
            let maskLayer1 = CAShapeLayer()
            maskLayer1.frame = bounds
            maskLayer1.path = maskPath1.cgPath
            layer.mask = maskLayer1
        }
    }
    

    在 viewDidAppear/viewDidLayoutSubviews 中调用:

    btnCorner.roundedButton()
    

    按钮角输出:

    【讨论】:

    • 你知道我怎样才能从按钮中删除它吗?如果我想重用按钮但不四舍五入? NVM,这里是:myBtn.layer.mask?.removeFromSuperlayer()
    • 当按钮在堆栈视图中时不起作用。圆角左下角和右下角时,它只圆左下角。使用未嵌入堆栈视图中的按钮时,它工作得很好
    • 在调整按钮大小时,使用这样的框架将不起作用。例如将按钮添加到 UIStackView。
    • 我怎样才能用这个扩展把四个角都弄圆?
    【解决方案5】:

    Swift 4:适用于最新的 iOS 11 及更高版本

    override func viewDidLoad() {
        super.viewDidLoad()
    
        if #available(iOS 11.0, *) {
            self.viewToRound.clipsToBounds = true
            viewToRound.layer.cornerRadius = 20
            viewToRound.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
        } else {
            // Fallback on earlier versions
        }
    }
    

    早期的 iO​​S(10,9 等)版本(也适用于 iOS 11)

    override func viewDidLayoutSubviews() {
        self.viewToRound.clipsToBounds = true
        let path = UIBezierPath(roundedRect: viewToRound.bounds,
                                byRoundingCorners: [.topRight, .topLeft],
                                cornerRadii: CGSize(width: 20, height: 20))
    
        let maskLayer = CAShapeLayer()
    
        maskLayer.path = path.cgPath
        viewToRound.layer.mask = maskLayer
    }
    

    【讨论】:

      【解决方案6】:

      iOS 11 让圆角变得非常容易。下面的代码将左上角和右下角四舍五入。

      myView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMaxYCorner]
      

      【讨论】:

      • 谢谢 .. /* 定义四个角中的哪个角在使用 * `cornerRadius' 属性时接收遮罩。默认为所有四个角。 */ .button.layer.cornerRadius = 8 button.layer.masksToBounds = true button.clipsToBounds = true button.layer.maskedCorners = [.layerMaxXMaxYCorner]
      【解决方案7】:

      更新你的扩展程序是这样的:

      extension UIView {
      func roundCorners(corners:UIRectCorner, radius: CGFloat) {
          let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
          let mask = CAShapeLayer()
          let rect = self.bounds
          mask.frame = rect
          mask.path = path.cgPath
          self.layer.mask = mask
      }
      }
      

      形状层(mask)需要知道frame

      【讨论】:

      • 感谢代码,它在很多场景中都非常有用。但请将“maskLayer.frame = rect”改为“mask.frame = rect”
      【解决方案8】:

      对于 swift 3,Kirit Modi 的回答改为:

      extension UIButton {
         func roundedButton(){
             let maskPAth1 = UIBezierPath(roundedRect: self.bounds,
                                          byRoundingCorners: [.topLeft , .topRight],
                                          cornerRadii:CGSize(width:8.0, height:8.0))
             let maskLayer1 = CAShapeLayer()
             maskLayer1.frame = self.bounds
             maskLayer1.path = maskPAth1.cgPath
             self.layer.mask = maskLayer1
         }
      }
      

      在扩展文件的开头不要忘记添加:

      import UIKit
      

      如果你想要一个 UIView 的扩展,你可以使用圆角或圆角的选项:

      extension UIView {
         func roundedCorners(top: Bool){
             let corners:UIRectCorner = (top ? [.topLeft , .topRight] : [.bottomRight , .bottomLeft])        
             let maskPAth1 = UIBezierPath(roundedRect: self.bounds,
                                          byRoundingCorners: corners,
                                          cornerRadii:CGSize(width:8.0, height:8.0))
             let maskLayer1 = CAShapeLayer()
             maskLayer1.frame = self.bounds
             maskLayer1.path = maskPAth1.cgPath
             self.layer.mask = maskLayer1
         }
      }
      

      按钮调用如下:

      myButton.roundedCorners(top: true)
      

      【讨论】:

        【解决方案9】:

        您忘记设置形状图层的框架:

        mask.frame = layer.bounds
        

        【讨论】:

          【解决方案10】:

          使用此代码,

          let path = UIBezierPath(roundedRect:viewTo.bounds, byRoundingCorners:[.TopRight, .TopLeft], cornerRadii: CGSizeMake(20, 20))
          let maskLayer = CAShapeLayer()
          maskLayer.path = path.CGPath
          viewTo.layer.mask = maskLayer
          

          希望对你有帮助

          【讨论】:

          • 兄弟-提问者已经调用了view.roundCorners([.TopLeft , .TopRight], radius: 10)之类的方法,您可以修改一次答案吗
          • 你知道提问者问但上面的代码是正确的
          猜你喜欢
          • 2016-04-29
          • 2023-04-01
          • 2018-02-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多