【问题标题】:How to set cornerRadius for only top-left and top-right corner of a UIView?如何仅为 UIView 的左上角和右上角设置cornerRadius?
【发布时间】:2012-04-27 09:04:24
【问题描述】:

有没有办法为UIView 的左上角和右上角设置cornerRadius

我尝试了以下方法,但最终看不到视图。

UIView *view = [[UIView alloc] initWithFrame:frame];

CALayer *layer = [CALayer layer];
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight) cornerRadii:CGSizeMake(3.0, 3.0)];
layer.shadowPath = shadowPath.CGPath;
view.layer.mask = layer;

【问题讨论】:

标签: ios cocoa-touch uiview cornerradius


【解决方案1】:

这是最好的方法Swift 5

import UIKit

extension UIView {

func roundCorners(radius: CGFloat = 10, corners: UIRectCorner = .allCorners) {
        self.clipsToBounds = true
        self.layer.cornerRadius = radius
        if #available(iOS 11.0, *) {
            var arr: CACornerMask = []
            
            let allCorners: [UIRectCorner] = [.topLeft, .topRight, .bottomLeft, .bottomRight, .allCorners]
            
            for corn in allCorners {
                if(corners.contains(corn)){
                    switch corn {
                    case .topLeft:
                        arr.insert(.layerMinXMinYCorner)
                    case .topRight:
                        arr.insert(.layerMaxXMinYCorner)
                    case .bottomLeft:
                        arr.insert(.layerMinXMaxYCorner)
                    case .bottomRight:
                        arr.insert(.layerMaxXMaxYCorner)
                    case .allCorners:
                        arr.insert(.layerMinXMinYCorner)
                        arr.insert(.layerMaxXMinYCorner)
                        arr.insert(.layerMinXMaxYCorner)
                        arr.insert(.layerMaxXMaxYCorner)
                    default: break
                    }
                }
            }
            self.layer.maskedCorners = arr
        } else {
            self.roundCornersBezierPath(corners: corners, radius: radius)
        }
    }
    
    private func roundCornersBezierPath(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
    }
    
}

【讨论】:

    【解决方案2】:

    使用这个扩展来设置圆角和圆角的圆边框

    这样使用:

    override func viewWillLayoutSubviews() {
                super.viewWillLayoutSubviews()
    
             myView.roundCornersWithBorder(corners: [.topLeft, .topRight], radius: 8.0)
        
            myView.roundCorners(corners: [.topLeft, .topRight], radius: 8.0)
    
            }
    
    
    
    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
        }
        
        func roundCornersWithBorder(corners: UIRectCorner, radius: CGFloat) {
            let maskLayer = CAShapeLayer()
            maskLayer.frame = bounds
            maskLayer.path = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: radius, height: radius)).cgPath
            
            layer.mask = maskLayer
            
            // Add border
            let borderLayer = CAShapeLayer()
            borderLayer.path = maskLayer.path // Reuse the Bezier path
            borderLayer.fillColor = UIColor.clear.cgColor
            borderLayer.strokeColor = UIColor(red:3/255, green:33/255, blue:70/255, alpha: 0.15).cgColor
            borderLayer.lineWidth = 2
            borderLayer.frame = bounds
            layer.addSublayer(borderLayer)
        }
        
    }
    

    【讨论】:

      【解决方案3】:

      使用这个扩展,它会涵盖一切。

      extension UIView {
      
         func roundTopCorners(radius: CGFloat = 10) {
          
             self.clipsToBounds = true
             self.layer.cornerRadius = radius
             if #available(iOS 11.0, *) {
                 self.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
             } else {
                 self.roundCorners(corners: [.topLeft, .topRight], radius: radius)
             }
         }
      
         func roundBottomCorners(radius: CGFloat = 10) {
          
             self.clipsToBounds = true
             self.layer.cornerRadius = radius
             if #available(iOS 11.0, *) {
                 self.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
             } else {
                 self.roundCorners(corners: [.bottomLeft, .bottomRight], radius: radius)
             }
         }
      
         private 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
          }
      }
      

      然后像这样使用它:-

      override func viewDidAppear(_ animated: Bool) {
          super.viewDidAppear(animated)
                  
          self.yourView.roundTopCorners()
      }
      

      注意:- 我建议你不要把这段代码放在 viewDidLayoutSubviews() 中,因为每当视图更新时,你都会在里面调用。所以使用 viewDidAppear(),它会像一个魅力一样工作。

      【讨论】:

      • 谢谢它的工作
      • @SourabhSharma 很高兴它有帮助:)
      【解决方案4】:

      Swift 4 Swift 5 1 行简单的方法

      用法:

      //MARK:- Corner Radius of only two side of UIViews
      self.roundCorners(view: yourview, corners: [.bottomLeft, .topRight], radius: 12.0)
      

      功能:

      //MARK:- Corner Radius of only two side of UIViews
      func roundCorners(view :UIView, corners: UIRectCorner, radius: CGFloat){
              let path = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
              let mask = CAShapeLayer()
              mask.path = path.cgPath
              view.layer.mask = mask
      }
      

      在 Objective-C 中

      用法:

      [self.verticalSeparatorView roundCorners:UIRectCornerTopLeft | UIRectCornerTopRight radius:10.0];

      Category 中使用的函数(只有一个角):

      -(void)roundCorners: (UIRectCorner) corners radius:(CGFloat)radius {
              UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)];
              CAShapeLayer *mask = [[CAShapeLayer alloc] init];
              mask.path = path.CGPath;
              self.layer.mask = mask;
          }
      

      【讨论】:

      • 只记得在 viewDidLayoutSubviews 完成之前不会计算视图的角,所以你应该在其中调用 roundCorners 函数
      • 先加圆角半径再加阴影
      • @JirsonTavera 谢谢你的小费,这让我发疯了,我几乎花了一个小时才在这里找到你的评论!
      • 此解决方案导致应用到图层的阴影不出现
      【解决方案5】:

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

      override func layoutSubviews() {
          super.layoutSubviews()
          roundCorners(corners: [.topLeft, .topRight], radius: 3.0)
      }
      

      如果你不这样做,它就不会出现。


      要圆角,请使用扩展名:

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


      其他视图控制器案例:无论您不能或不想子类化视图,您仍然可以对视图进行舍入。通过覆盖 viewWillLayoutSubviews() 函数从其视图控制器执行此操作,如下所示:

      class MyVC: UIViewController {
          /// The view to round the top-left and top-right hand corners
          let theView: UIView = {
              let v = UIView(frame: CGRect(x: 10, y: 10, width: 200, height: 200))
              v.backgroundColor = .red
              return v
          }()
          
          override func loadView() {
              super.loadView()
              view.addSubview(theView)
          }
          
          override func viewWillLayoutSubviews() {
              super.viewWillLayoutSubviews()
      
              // Call the roundCorners() func right there.
              theView.roundCorners(corners: [.topLeft, .topRight], radius: 30)
          }
      }
      

      【讨论】:

      • 答案最近已经修复..@kelin
      • 这绝对是拐角处。
      • 您必须在视图出现后执行此操作
      • 如果有人遇到与我相同的问题 - 如果您在 ViewController 中编写代码,请不要忘记 override func viewDidLayoutSubviews() { roundCorners() }
      • UIBezierPath 与固定尺寸视图一起使用,但是当视图尺寸因自动布局约束而改变时会产生问题
      【解决方案6】:

      有一种超级简单的方法。我在 here 上找到的。

      view.clipsToBounds = true
      view.layer.cornerRadius = 24
      view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
      

      它在视图的CALayer 上使用stock cornerRadius 属性。您只需要定义角。 layerMinXMinYCorner 是左上角 layerMaxXMinYCorner 是右上角。

      【讨论】:

      • 我喜欢这个答案,简洁明了。
      【解决方案7】:

      在 Swift 4.1 和 Xcode 9.4.1 中

      iOS 11 中,这一行就足够了:

      detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]//Set your view here
      

      查看完整代码:

      //In viewDidLoad
      if #available(iOS 11.0, *) {
              detailsSubView.clipsToBounds = false
              detailsSubView.layer.cornerRadius = 10
              detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
      } else {
            //For lower versions
      }
      

      但对于低版本

      let rectShape = CAShapeLayer()
          rectShape.bounds = detailsSubView.frame
          rectShape.position = detailsSubView.center
          rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds,    byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
          detailsSubView.layer.mask = rectShape
      

      完整的代码是。

      if #available(iOS 11.0, *) {
          detailsSubView.clipsToBounds = false
          detailsSubView.layer.cornerRadius = 10
          detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
      } else {
          let rectShape = CAShapeLayer()
          rectShape.bounds = detailsSubView.frame
          rectShape.position = detailsSubView.center
          rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds,    byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
          detailsSubView.layer.mask = rectShape
      }
      

      如果您在情节提要中使用 AutoResizing,请在 viewDidLayoutSubviews() 中编写此代码。

      override func viewDidLayoutSubviews() {
          super.viewDidLayoutSubviews()
      
          if #available(iOS 11.0, *) {
              detailsSubView.clipsToBounds = false
              detailsSubView.layer.cornerRadius = 10
              detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
          } else {
              let rectShape = CAShapeLayer()
              rectShape.bounds = detailsSubView.frame
              rectShape.position = detailsSubView.center
              rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds,    byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
              detailsSubView.layer.mask = rectShape
          }
      }
      

      【讨论】:

      • ios 9 有什么解决方案吗?
      • @jay let rectShape = CAShapeLayer() rectShape.bounds = detailsS​​ubView.frame rectShape.position = detailsS​​ubView.center rectShape.path = UIBezierPath(roundedRect: detailsS​​ubView.bounds, byRoundingCorners: [.topLeft, .topRight ],cornerRadii: CGSize(width: 20, height: 20)).cgPath detailsS​​ubView.layer.mask = rectShape 此代码适用于 iOS 9
      • 不适用于 ios 9。角落部分没有边框。
      • @jay 我没有 iOS 9 操作系统手机,但我检查了 iOS 9 模拟器。它正在工作...您检查的方式和位置。你能建议我签入 iOS 9
      • 我签入了模拟器..这里是docs.google.com/document/d/…
      【解决方案8】:

      对于SwiftUI

      我找到了这些解决方案,您可以从这里查看https://stackoverflow.com/a/56763282/3716103

      我强烈推荐第一个

      选项 1:使用 Path + GeometryReader

      (有关 GeometryReader 的更多信息:https://swiftui-lab.com/geometryreader-to-the-rescue/

      struct ContentView : View {
          var body: some View {
      
              Text("Hello World!")
                  .foregroundColor(.white)
                  .font(.largeTitle)
                  .padding(20)
                  .background(RoundedCorners(color: .blue, tl: 0, tr: 30, bl: 30, br: 0))
          }
      }
      

      RoundedCorners

      struct RoundedCorners: View {
      
          var color: Color = .white
      
          var tl: CGFloat = 0.0
          var tr: CGFloat = 0.0
          var bl: CGFloat = 0.0
          var br: CGFloat = 0.0
      
          var body: some View {
              GeometryReader { geometry in
                  Path { path in
      
                      let w = geometry.size.width
                      let h = geometry.size.height
      
                      // Make sure we do not exceed the size of the rectangle
                      let tr = min(min(self.tr, h/2), w/2)
                      let tl = min(min(self.tl, h/2), w/2)
                      let bl = min(min(self.bl, h/2), w/2)
                      let br = min(min(self.br, h/2), w/2)
      
                      path.move(to: CGPoint(x: w / 2.0, y: 0))
                      path.addLine(to: CGPoint(x: w - tr, y: 0))
                      path.addArc(center: CGPoint(x: w - tr, y: tr), radius: tr, startAngle: Angle(degrees: -90), endAngle: Angle(degrees: 0), clockwise: false)
                      path.addLine(to: CGPoint(x: w, y: h - be))
                      path.addArc(center: CGPoint(x: w - br, y: h - br), radius: br, startAngle: Angle(degrees: 0), endAngle: Angle(degrees: 90), clockwise: false)
                      path.addLine(to: CGPoint(x: bl, y: h))
                      path.addArc(center: CGPoint(x: bl, y: h - bl), radius: bl, startAngle: Angle(degrees: 90), endAngle: Angle(degrees: 180), clockwise: false)
                      path.addLine(to: CGPoint(x: 0, y: tl))
                      path.addArc(center: CGPoint(x: tl, y: tl), radius: tl, startAngle: Angle(degrees: 180), endAngle: Angle(degrees: 270), clockwise: false)
                  }
                  .fill(self.color)
              }
          }
      }
      

      RoundedCorners_Previews

      struct RoundedCorners_Previews: PreviewProvider {
          static var previews: some View {
              RoundedCorners(color: .pink, tl: 40, tr: 40, bl: 40, br: 40)
          }
      }
      

      【讨论】:

        【解决方案9】:

        简单的扩展

        extension UIView {
            func roundCorners(corners: UIRectCorner, radius: CGFloat) {
                if #available(iOS 11, *) {
                    self.clipsToBounds = true
                    self.layer.cornerRadius = radius
                    var masked = CACornerMask()
                    if corners.contains(.topLeft) { masked.insert(.layerMinXMinYCorner) }
                    if corners.contains(.topRight) { masked.insert(.layerMaxXMinYCorner) }
                    if corners.contains(.bottomLeft) { masked.insert(.layerMinXMaxYCorner) }
                    if corners.contains(.bottomRight) { masked.insert(.layerMaxXMaxYCorner) }
                    self.layer.maskedCorners = masked
                }
                else {
                    let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
                    let mask = CAShapeLayer()
                    mask.path = path.cgPath
                    layer.mask = mask
                }
            }
        }
        

        用法:

        view.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 12)
        

        【讨论】:

          【解决方案10】:

          我在 swift 中舍入 UIView 和 UITextFiels 特定角的解决方案是使用

          .layer.cornerRadius

          layer.maskedCorners

          实际的 UIView 或 UITextFields。

          示例:

          fileprivate func inputTextFieldStyle() {
                  inputTextField.layer.masksToBounds = true
                  inputTextField.layer.borderWidth = 1
                  inputTextField.layer.cornerRadius = 25
                  inputTextField.layer.maskedCorners = [.layerMaxXMaxYCorner,.layerMaxXMinYCorner]
                  inputTextField.layer.borderColor = UIColor.white.cgColor
              }
          

          并且通过使用

          .layerMaxXMaxYCorner

          .layerMaxXMinYCorner

          ,我可以指定UITextField的右上角和右下角为圆角。

          您可以在此处查看结果:

          【讨论】:

          • 非常适合边框和特定角的组合???
          • 完美解决方案
          【解决方案11】:

          这将是最简单的答案:

          yourView.layer.cornerRadius = 8
          yourView.layer.masksToBounds = true
          yourView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
          

          【讨论】:

          • 标记是iOS 11或以上的解决方案
          【解决方案12】:

          如果您正在寻找一种仅限界面构建器的解决方案,则可以找到适用于 iOS 11 及更高版本的解决方案。在这里查看我的答案:https://stackoverflow.com/a/58626264

          【讨论】:

            【解决方案13】:

            在 Swift 4.2 中,通过 @IBDesignable 创建它,如下所示:

            @IBDesignable
            
            class DesignableViewCustomCorner: UIView {
            
                @IBInspectable var cornerRadious: CGFloat = 0 {
                    didSet {
                        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: cornerRadious, height: cornerRadious))
                        let mask = CAShapeLayer()
                        mask.path = path.cgPath
                        self.layer.mask = mask
                    }
                }
            
            }
            

            【讨论】:

              【解决方案14】:

              更改代码后@apinho 在 swift 4.3 中工作正常

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

              为您使用此功能查看

              YourViewName. roundCornersWithLayerMask(cornerRadii: 20,corners: [.topLeft,.topRight])
              

              【讨论】:

                【解决方案15】:

                Stephane 的另一个版本的回答。

                import UIKit
                
                    class RoundCornerView: UIView {
                    var corners : UIRectCorner = [.topLeft,.topRight,.bottomLeft,.bottomRight]
                        var roundCornerRadius : CGFloat = 0.0
                        override func layoutSubviews() {
                            super.layoutSubviews()
                            if corners.rawValue > 0 && roundCornerRadius > 0.0 {
                                self.roundCorners(corners: corners, radius: roundCornerRadius)
                            }
                        }
                        private 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
                        }
                
                    }
                

                【讨论】:

                  【解决方案16】:

                  Emma:.TopRight.BottomRight 对您不起作用,可能是因为对 view.roundCorners 的调用是在计算最终 view bounds 之前完成的。请注意,Bezier Path 派生自调用时的视图边界。例如,如果自动布局会使视图变窄,则右侧的圆角可能在视图之外。 尝试在 viewDidLayoutSubviews 中调用它,其中视图的绑定是最终的。

                  【讨论】:

                  • 谢谢。对我来说,解决这个问题的方法是将调用从 viewDidLoad 和 viewWillAppear 转移到 viewDidAppear 中的“Arbitur”。我可以这样做,因为我的控件最初设置为隐藏。
                  • 你是对的。它会产生自动布局的问题,你做得很好。
                  【解决方案17】:

                  斯威夫特 4

                  extension UIView {
                  
                      func roundTop(radius:CGFloat = 5){
                          self.clipsToBounds = true
                          self.layer.cornerRadius = radius
                          if #available(iOS 11.0, *) {
                              self.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
                          } else {
                              // Fallback on earlier versions
                          }
                      }
                  
                      func roundBottom(radius:CGFloat = 5){
                          self.clipsToBounds = true
                          self.layer.cornerRadius = radius
                          if #available(iOS 11.0, *) {
                              self.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]
                          } else {
                              // Fallback on earlier versions
                          }
                      }
                  }
                  

                  【讨论】:

                  • 在我的情况下,您节省了我的一天,我不得不为特定单元格制作四舍五入的表格视图
                  • 根据我的要求完美回答。我使用了所有答案,对我没有任何帮助,但是您的答案帮助了我并解决了我的问题。
                  【解决方案18】:

                  最后……iOS11 中有CACornerMask! 使用CACornerMask 可以很容易地完成:

                  let view = UIView()
                  view.clipsToBounds = true
                  view.layer.cornerRadius = 10
                  view.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner] // Top right corner, Top left corner respectively
                  

                  【讨论】:

                  • 这绝对是最好的。在动态调整表格视图单元格的边缘时,我们总是遇到其他解决方案的问题。
                  • 旧版本怎么办? self.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner,.layerMaxXMinYCorner]
                  • @SHEBIN,尝试本页其他答案的解决方案
                  • 旋转设备时其他答案不起作用,此代码适用于旋转并允许您绕过某些角落,这应该是公认的答案。
                  • 这应该是最佳答案。这是对OP问题的最直接和最相关的答案。
                  【解决方案19】:

                  iOS 11 、Swift 4
                  你可以试试这个代码:

                  if #available(iOS 11.0, *) {
                     element.clipsToBounds = true
                     element.layer.cornerRadius = CORNER_RADIUS
                     element.layer.maskedCorners = [.layerMaxXMaxYCorner]
                  } else {
                     // Fallback on earlier versions
                  }
                  

                  您可以在表格视图单元格中使用它。

                  【讨论】:

                  • 这是当今编码的正确答案。再见遮罩层。
                  • 这一定是最佳答案!
                  【解决方案20】:

                  这是@JohnnyRockex 答案的Swift 版本

                  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, .bottomRight], radius: 10)
                  

                  注意

                  如果您使用自动布局,则需要将UIView 子类化并在视图的layoutSubviews 中调用roundCorners 以获得最佳效果。

                  class View: UIView {
                      override func layoutSubviews() {
                          super.layoutSubviews()
                  
                          self.roundCorners([.topLeft, .bottomLeft], radius: 10)
                      }
                  }
                  

                  【讨论】:

                  • 很棒的扩展。但是:.TopRight.BottomRight 似乎对我不起作用。
                  • Swift 2 上:view.roundCorners([.TopLeft , .BottomLeft], radius: 10)
                  • 右侧无法正常工作,因为您的视图边界尚未通过自动布局很好地定义...我目前面临同样的问题。
                  • @dosdos 子类,视图和 layoutSubviews 围绕自我的角落。
                  • 如果你使用自动布局,并且没有对视图的引用想圆,你可以调用.layoutIfNeeded(),然后这个方法。
                  【解决方案21】:

                  这是一个像这样实现的简短方法:

                  - (void)viewDidLoad {
                      [super viewDidLoad];
                      UIButton *openInMaps = [UIButton new];
                      [openInMaps setFrame:CGRectMake(15, 135, 114, 70)];
                      openInMaps = (UIButton *)[self roundCornersOnView:openInMaps onTopLeft:NO topRight:NO bottomLeft:YES bottomRight:NO radius:5.0];
                  }
                  
                  - (UIView *)roundCornersOnView:(UIView *)view onTopLeft:(BOOL)tl topRight:(BOOL)tr bottomLeft:(BOOL)bl bottomRight:(BOOL)br radius:(float)radius {
                  
                      if (tl || tr || bl || br) {
                          UIRectCorner corner = 0;
                          if (tl) {corner = corner | UIRectCornerTopLeft;}
                          if (tr) {corner = corner | UIRectCornerTopRight;}
                          if (bl) {corner = corner | UIRectCornerBottomLeft;}
                          if (br) {corner = corner | UIRectCornerBottomRight;}
                  
                          UIView *roundedView = view;
                          UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:roundedView.bounds byRoundingCorners:corner cornerRadii:CGSizeMake(radius, radius)];
                          CAShapeLayer *maskLayer = [CAShapeLayer layer];
                          maskLayer.frame = roundedView.bounds;
                          maskLayer.path = maskPath.CGPath;
                          roundedView.layer.mask = maskLayer;
                          return roundedView;
                      }
                      return view;
                  }
                  

                  【讨论】:

                  • 设置颜色怎么样? maskLayer.borderWidth = 10; maskLayer.borderColor = [UIColor redColor].CGColor;先生,它不适合我。
                  • @kiran 一个面具没有颜色,如果你想有一个边框,你可以添加第二个 CAShapeLayer
                  【解决方案22】:

                  我不确定为什么您的解决方案不起作用,但以下代码对我有用。创建一个贝塞尔蒙版并将其应用于您的视图。在下面的代码中,我将_backgroundView 的底角圆角为3 像素。 self 是自定义的UITableViewCell

                  UIBezierPath *maskPath = [UIBezierPath
                      bezierPathWithRoundedRect:self.backgroundImageView.bounds
                      byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight)
                      cornerRadii:CGSizeMake(20, 20)
                  ];
                  
                  CAShapeLayer *maskLayer = [CAShapeLayer layer];
                  
                  maskLayer.frame = self.bounds;
                  maskLayer.path = maskPath.CGPath;
                  
                  self.backgroundImageView.layer.mask = maskLayer;
                  

                  有一些改进的 Swift 版本:

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

                  Swift 3.0 版本:

                  let path = UIBezierPath(roundedRect:viewToRound.bounds,
                                          byRoundingCorners:[.topRight, .bottomLeft],
                                          cornerRadii: CGSize(width: 20, height:  20))
                  
                  let maskLayer = CAShapeLayer()
                  
                  maskLayer.path = path.cgPath
                  viewToRound.layer.mask = maskLayer
                  

                  Swift 扩展here

                  【讨论】:

                  • 在文本字段中尝试。左边成功,右边失败
                  • @RainerLiao 我有同样的问题,我在viewDidLoad 方法上做了所有这些,将它移到viewDidAppear 并且它有效。
                  • 如何将其设置为适用于任何设备。这仅适用于故事板中的simulator 大小。 ex: if the simulator size is 6s it works fine for 6s, but not of others. 我该如何克服这个问题。
                  • Swift 3 版本中的小语法错误:path.CGPath 应该是 path.cgPath
                  • 不适用于底部。即 bottomLeft & bottomRight
                  【解决方案23】:

                  重用 Yunus Nedim Mehel 解决方案的可爱扩展

                  斯威夫特 2.3

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

                  用法

                  let view = UIView()
                  view.roundCornersWithLayerMask(10,[.TopLeft,.TopRight])
                  

                  【讨论】:

                  • 不错的清洁解决方案
                  【解决方案24】:

                  这是您可以使用 C# 中的 Xamarin 为按钮的每个角设置角半径的方法:

                  var maskPath = UIBezierPath.FromRoundedRect(MyButton.Bounds, UIRectCorner.BottomLeft | UIRectCorner.BottomRight,
                      new CGSize(10.0, 10.0));
                  var maskLayer = new CAShapeLayer
                  {
                      Frame = MyButton.Bounds,
                      Path = maskPath.CGPath
                  };
                  MyButton.Layer.Mask = maskLayer;
                  

                  【讨论】:

                    【解决方案25】:

                    此处为 Swift 代码示例:https://stackoverflow.com/a/35621736/308315


                    不直接。您必须:

                    1. 创建一个CAShapeLayer
                    2. 将其path 设置为基于view.boundsCGPathRef,但只有两个圆角(可能使用+[UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:]
                    3. 将您的view.layer.mask 设置为CAShapeLayer

                    【讨论】:

                    • 请注意,如果您在多个视图上执行此操作,则会损害性能...
                    • @jjxtra 那么在没有太多性能损失的情况下,最好的方法是什么?我想在 UITableViewCell 中显示它。
                    • @xi.lin 我记得设置 layer.shouldRasterize == YES 将速度提高了 5 倍左右。但是文档说它只有在您使用非透明单元格时才有效。试一试。
                    【解决方案26】:
                        // Create the path (with only the top-left corner rounded)
                    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds 
                                               byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight) 
                                               cornerRadii:CGSizeMake(7.0, 7.0)];
                    
                    // Create the shape layer and set its path
                    CAShapeLayer *maskLayer = [CAShapeLayer layer];
                    maskLayer.frame = cell.stripBlackImnageView.bounds;
                    maskLayer.path = maskPath.CGPath; 
                    // Set the newly created shapelayer as the mask for the image view's layer
                    view.layer.mask = maskLayer;
                    

                    【讨论】:

                      【解决方案27】:

                      已经给出的所有答案都非常好且有效(尤其是尤努斯使用mask 属性的想法)。

                      但是我需要一些更复杂的东西,因为我的层经常会改变大小,这意味着我每次都需要调用屏蔽逻辑,这有点烦人。

                      我使用 swift extensions 和计算属性构建了一个真正的 cornerRadii 属性,该属性负责在布局图层时自动更新蒙版。

                      这是通过使用 Peter Steinberg 伟大的 Aspects 库来实现的。

                      完整代码在这里:

                      extension CALayer {
                        // This will hold the keys for the runtime property associations
                        private struct AssociationKey {
                          static var CornerRect:Int8 = 1    // for the UIRectCorner argument
                          static var CornerRadius:Int8 = 2  // for the radius argument
                        }
                      
                        // new computed property on CALayer
                        // You send the corners you want to round (ex. [.TopLeft, .BottomLeft])
                        // and the radius at which you want the corners to be round
                        var cornerRadii:(corners: UIRectCorner, radius:CGFloat) {
                          get {
                            let number = objc_getAssociatedObject(self, &AssociationKey.CornerRect)  as? NSNumber ?? 0
                            let radius = objc_getAssociatedObject(self, &AssociationKey.CornerRadius)  as? NSNumber ?? 0
                            return (corners: UIRectCorner(rawValue: number.unsignedLongValue), radius: CGFloat(radius.floatValue))
                          }
                          set (v) {
                            let radius = v.radius
                            let closure:((Void)->Void) = {
                              let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: v.corners, cornerRadii: CGSize(width: radius, height: radius))
                              let mask = CAShapeLayer()
                              mask.path = path.CGPath
                              self.mask = mask
                            }
                            let block: @convention(block) Void -> Void = closure
                            let objectBlock = unsafeBitCast(block, AnyObject.self)
                            objc_setAssociatedObject(self, &AssociationKey.CornerRect, NSNumber(unsignedLong: v.corners.rawValue), .OBJC_ASSOCIATION_RETAIN)
                            objc_setAssociatedObject(self, &AssociationKey.CornerRadius, NSNumber(float: Float(v.radius)), .OBJC_ASSOCIATION_RETAIN)
                            do { try aspect_hookSelector("layoutSublayers", withOptions: .PositionAfter, usingBlock: objectBlock) }
                            catch _ { }
                          }
                        }
                      }
                      

                      我写了一个简单的blog post 解释这一点。

                      【讨论】:

                        【解决方案28】:

                        试试这个代码,

                        UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:( UIRectCornerTopLeft | UIRectCornerTopRight) cornerRadii:CGSizeMake(5.0, 5.0)];
                        
                        CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
                        maskLayer.frame = self.view.bounds;
                        maskLayer.path  = maskPath.CGPath;
                        
                        view.layer.mask = maskLayer;
                        

                        【讨论】:

                          【解决方案29】:

                          以编程方式执行此操作的一种方法是在具有圆角的UIView 的顶部创建一个UIView。或者您可以将顶部隐藏在某物下方。

                          【讨论】:

                          • 这是一个非常丑陋的解决方案:P
                          【解决方案30】:

                          最简单的方法是制作带有圆角图层的蒙版。

                          CALayer *maskLayer = [CALayer layer];
                          maskLayer.frame = CGRectMake(0,0,maskWidth ,maskHeight);
                          maskLayer.contents = (__bridge id)[[UIImage imageNamed:@"maskImageWithRoundedCorners.png"] CGImage];
                          
                          aUIView.layer.mask = maskLayer;
                          

                          别忘了:

                          #import <QuartzCore/QuartzCore.h>
                          

                          【讨论】:

                            猜你喜欢
                            • 2014-10-26
                            • 2015-09-22
                            • 1970-01-01
                            • 2020-05-07
                            • 1970-01-01
                            • 2012-02-17
                            • 2011-04-14
                            • 1970-01-01
                            相关资源
                            最近更新 更多