【问题标题】:How to add a border just on the top side of a UIView如何在 UIView 的顶部添加边框
【发布时间】:2013-06-25 16:05:36
【问题描述】:

我的问题在标题上。

我不知道如何在特定的一侧、顶部或底部、任何一侧添加边框... layer.border为整个视图绘制边框...

【问题讨论】:

标签: ios objective-c xcode uiview border


【解决方案1】:

Adam Waite's original post 增加了圆角功能,以及多次编辑

重要提示!:如前所述,不要忘记在调用“addborder”之前添加“label.layoutIfNeeded()”

注意:我只在 UILabels 上测试过这个。

extension CALayer {
    
    enum BorderSide {
        case top
        case right
        case bottom
        case left
        case notRight
        case notLeft
        case topAndBottom
        case all
    }
    
    enum Corner {
        case topLeft
        case topRight
        case bottomLeft
        case bottomRight
    }
    
    func addBorder(side: BorderSide, thickness: CGFloat, color: CGColor, maskedCorners: CACornerMask? = nil) {
        var topWidth = frame.size.width; var bottomWidth = topWidth
        var leftHeight = frame.size.height; var rightHeight = leftHeight
        
        var topXOffset: CGFloat = 0; var bottomXOffset: CGFloat = 0
        var leftYOffset: CGFloat = 0; var rightYOffset: CGFloat = 0
        
        // Draw the corners and set side offsets
        switch maskedCorners {
        case [.layerMinXMinYCorner, .layerMaxXMinYCorner]: // Top only
            addCorner(.topLeft, thickness: thickness, color: color)
            addCorner(.topRight, thickness: thickness, color: color)
            topWidth -= cornerRadius*2
            leftHeight -= cornerRadius; rightHeight -= cornerRadius
            topXOffset = cornerRadius; leftYOffset = cornerRadius; rightYOffset = cornerRadius
            
        case [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]: // Bottom only
            addCorner(.bottomLeft, thickness: thickness, color: color)
            addCorner(.bottomRight, thickness: thickness, color: color)
            bottomWidth -= cornerRadius*2
            leftHeight -= cornerRadius; rightHeight -= cornerRadius
            bottomXOffset = cornerRadius
            
        case [.layerMinXMinYCorner, .layerMinXMaxYCorner]: // Left only
            addCorner(.topLeft, thickness: thickness, color: color)
            addCorner(.bottomLeft, thickness: thickness, color: color)
            topWidth -= cornerRadius; bottomWidth -= cornerRadius
            leftHeight -= cornerRadius*2
            leftYOffset = cornerRadius; topXOffset = cornerRadius; bottomXOffset = cornerRadius;
            
        case [.layerMaxXMinYCorner, .layerMaxXMaxYCorner]: // Right only
            addCorner(.topRight, thickness: thickness, color: color)
            addCorner(.bottomRight, thickness: thickness, color: color)
            topWidth -= cornerRadius; bottomWidth -= cornerRadius
            rightHeight -= cornerRadius*2
            rightYOffset = cornerRadius
            
        case [.layerMaxXMinYCorner, .layerMaxXMaxYCorner,  // All
              .layerMinXMaxYCorner, .layerMinXMinYCorner]:
            addCorner(.topLeft, thickness: thickness, color: color)
            addCorner(.topRight, thickness: thickness, color: color)
            addCorner(.bottomLeft, thickness: thickness, color: color)
            addCorner(.bottomRight, thickness: thickness, color: color)
            topWidth -= cornerRadius*2; bottomWidth -= cornerRadius*2
            topXOffset = cornerRadius; bottomXOffset = cornerRadius
            leftHeight -= cornerRadius*2; rightHeight -= cornerRadius*2
            leftYOffset = cornerRadius; rightYOffset = cornerRadius
            
        default: break
        }
        
        // Draw the sides
        switch side {
        case .top:
            addLine(x: topXOffset, y: 0, width: topWidth, height: thickness, color: color)
            
        case .right:
            addLine(x: frame.size.width - thickness, y: rightYOffset, width: thickness, height: rightHeight, color: color)
            
        case .bottom:
            addLine(x: bottomXOffset, y: frame.size.height - thickness, width: bottomWidth, height: thickness, color: color)
            
        case .left:
            addLine(x: 0, y: leftYOffset, width: thickness, height: leftHeight, color: color)

        // Multiple Sides
        case .notRight:
            addLine(x: topXOffset, y: 0, width: topWidth, height: thickness, color: color)
            addLine(x: 0, y: leftYOffset, width: thickness, height: leftHeight, color: color)
            addLine(x: bottomXOffset, y: frame.size.height - thickness, width: bottomWidth, height: thickness, color: color)

        case .notLeft:
            addLine(x: topXOffset, y: 0, width: topWidth, height: thickness, color: color)
            addLine(x: frame.size.width - thickness, y: rightYOffset, width: thickness, height: rightHeight, color: color)
            addLine(x: bottomXOffset, y: frame.size.height - thickness, width: bottomWidth, height: thickness, color: color)

        case .topAndBottom:
            addLine(x: topXOffset, y: 0, width: topWidth, height: thickness, color: color)
            addLine(x: bottomXOffset, y: frame.size.height - thickness, width: bottomWidth, height: thickness, color: color)

        case .all:
            addLine(x: topXOffset, y: 0, width: topWidth, height: thickness, color: color)
            addLine(x: frame.size.width - thickness, y: rightYOffset, width: thickness, height: rightHeight, color: color)
            addLine(x: bottomXOffset, y: frame.size.height - thickness, width: bottomWidth, height: thickness, color: color)
            addLine(x: 0, y: leftYOffset, width: thickness, height: leftHeight, color: color)
        }
    }
    
    private func addLine(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat, color: CGColor) {
        let border = CALayer()
        border.frame = CGRect(x: x, y: y, width: width, height: height)
        border.backgroundColor = color
        addSublayer(border)
    }
    
    private func addCorner(_ corner: Corner, thickness: CGFloat, color: CGColor) {
        // Set default to top left
        let width = frame.size.width; let height = frame.size.height
        var x = cornerRadius
        var y = cornerRadius
        var startAngle: CGFloat = .pi; var endAngle: CGFloat = .pi*3/2
        
        switch corner {
        case .bottomLeft:
            y = height - cornerRadius 
            startAngle = .pi/2; endAngle = .pi
            
        case .bottomRight:
            x = width - cornerRadius
            y = height - cornerRadius
            startAngle = 0; endAngle = .pi/2
            
        case .topRight:
            x = width - cornerRadius
            startAngle = .pi*3/2; endAngle = 0
            
        default: break
        }
        
        let cornerPath = UIBezierPath(arcCenter: CGPoint(x: x, y: y),
                                      radius: cornerRadius - thickness,
                                      startAngle: startAngle,
                                      endAngle: endAngle,
                                      clockwise: true)

        let cornerShape = CAShapeLayer()
        cornerShape.path = cornerPath.cgPath
        cornerShape.lineWidth = thickness
        cornerShape.strokeColor = color
        cornerShape.fillColor = nil
        addSublayer(cornerShape)
    }
}

【讨论】:

  • 在更改了每个 Swift 3 的 CGRectMake 签名和 CGColor 之后,由于某种原因,此代码无法在 Swift 3 上运行。
  • 这里有一篇很好的文章medium.com/swift-programming/… 讨论了你需要为 Swift 3 做些什么。
  • 在 swift 3 中实现这个有什么运气吗?
  • 要使其工作,您需要在调用view.layer.addBorder(...) 之前添加view.layoutIfNeeded()。然后它在 Swift 3 中工作
  • 一切正常。在此方法中添加行override func viewDidLayoutSubviews()
【解决方案2】:

对我来说最好的方法是 UIView 上的一个类别,但 adding views 而不是 CALayers,所以我们可以take advantage of AutoresizingMasks 来确保边框与超级视图一起调整大小。

目标 C

- (void)addTopBorderWithColor:(UIColor *)color andWidth:(CGFloat) borderWidth {
    UIView *border = [UIView new];
    border.backgroundColor = color;
    [border setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin];
    border.frame = CGRectMake(0, 0, self.frame.size.width, borderWidth);
    [self addSubview:border];
}

- (void)addBottomBorderWithColor:(UIColor *)color andWidth:(CGFloat) borderWidth {
    UIView *border = [UIView new];
    border.backgroundColor = color;
    [border setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin];
    border.frame = CGRectMake(0, self.frame.size.height - borderWidth, self.frame.size.width, borderWidth);
    [self addSubview:border];
}

- (void)addLeftBorderWithColor:(UIColor *)color andWidth:(CGFloat) borderWidth {
    UIView *border = [UIView new];
    border.backgroundColor = color;
    border.frame = CGRectMake(0, 0, borderWidth, self.frame.size.height);
    [border setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleRightMargin];
    [self addSubview:border];
}

- (void)addRightBorderWithColor:(UIColor *)color andWidth:(CGFloat) borderWidth {
    UIView *border = [UIView new];
    border.backgroundColor = color;
    [border setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin];
    border.frame = CGRectMake(self.frame.size.width - borderWidth, 0, borderWidth, self.frame.size.height);
    [self addSubview:border];
}

斯威夫特 5

func addTopBorder(with color: UIColor?, andWidth borderWidth: CGFloat) {
    let border = UIView()
    border.backgroundColor = color
    border.autoresizingMask = [.flexibleWidth, .flexibleBottomMargin]
    border.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: borderWidth)
    addSubview(border)
}

func addBottomBorder(with color: UIColor?, andWidth borderWidth: CGFloat) {
    let border = UIView()
    border.backgroundColor = color
    border.autoresizingMask = [.flexibleWidth, .flexibleTopMargin]
    border.frame = CGRect(x: 0, y: frame.size.height - borderWidth, width: frame.size.width, height: borderWidth)
    addSubview(border)
}

func addLeftBorder(with color: UIColor?, andWidth borderWidth: CGFloat) {
    let border = UIView()
    border.backgroundColor = color
    border.frame = CGRect(x: 0, y: 0, width: borderWidth, height: frame.size.height)
    border.autoresizingMask = [.flexibleHeight, .flexibleRightMargin]
    addSubview(border)
}

func addRightBorder(with color: UIColor?, andWidth borderWidth: CGFloat) {
    let border = UIView()
    border.backgroundColor = color
    border.autoresizingMask = [.flexibleHeight, .flexibleLeftMargin]
    border.frame = CGRect(x: frame.size.width - borderWidth, y: 0, width: borderWidth, height: frame.size.height)
    addSubview(border)
}

【讨论】:

  • 这是迄今为止解决此问题的最佳方法之一。大多数其他解决方案不支持视图更改(因此设备旋转或拆分视图)。这个可以。
  • 如何调整以支持圆角?
  • 该死!即使我在自定义视图的 init 中打印 (self.frame.width) 我得到 0,这也像魔术一样工作。但顶部边框是正确的!
【解决方案3】:

Swift 3.0

斯威夫特 4.1

extension CALayer {

  func addBorder(edge: UIRectEdge, color: UIColor, thickness: CGFloat) {

    let border = CALayer()

    switch edge {
    case UIRectEdge.top:
        border.frame = CGRect(x: 0, y: 0, width: frame.width, height: thickness)

    case UIRectEdge.bottom:
        border.frame = CGRect(x:0, y: frame.height - thickness, width: frame.width, height:thickness)

    case UIRectEdge.left:
        border.frame = CGRect(x:0, y:0, width: thickness, height: frame.height)

    case UIRectEdge.right:
        border.frame = CGRect(x: frame.width - thickness, y: 0, width: thickness, height: frame.height)

    default: do {}
    }

    border.backgroundColor = color.cgColor

    addSublayer(border)
 }
}

【讨论】:

  • 这在视图调整大小时不起作用,例如方向改变。
  • 如果您使用基于框架的布局,那么您必须实现 layoutSubviews 并重新计算其中的所有子视图(或子层)框架
  • 也不能作为本身具有圆角半径的视图的边框
【解决方案4】:

Swift 4.2 和自动布局

我浏览了提供的解决方案。许多基于框架 这是一个与 AutoLayout 一起使用的简单扩展 - 使用 View 而不是 Layer 以确保我们可以使用 AutoLayout - 具有 4 个约束的单个子视图

如下使用:

self.addBorder(.bottom, color: .lightGray, thickness: 0.5)


extension UIView {
    func addBorder(_ edge: UIRectEdge, color: UIColor, thickness: CGFloat) {
        let subview = UIView()
        subview.translatesAutoresizingMaskIntoConstraints = false
        subview.backgroundColor = color
        self.addSubview(subview)
        switch edge {
        case .top, .bottom:
            subview.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0).isActive = true
            subview.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0).isActive = true
            subview.heightAnchor.constraint(equalToConstant: thickness).isActive = true
            if edge == .top {
                subview.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
            } else {
                subview.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
            }
        case .left, .right:
            subview.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
            subview.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
            subview.widthAnchor.constraint(equalToConstant: thickness).isActive = true
            if edge == .left {
                subview.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0).isActive = true
            } else {
                subview.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0).isActive = true
            }
        default:
            break
        }
    }
}

【讨论】:

    【解决方案5】:

    Swift 3 版本

    extension UIView {
        enum ViewSide {
            case Top, Bottom, Left, Right
        }
    
        func addBorder(toSide side: ViewSide, withColor color: UIColor, andThickness thickness: CGFloat) {
    
            let border = CALayer()
            border.backgroundColor = color.cgColor
    
            switch side {
            case .Top:
                border.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: thickness)
            case .Bottom:
                border.frame = CGRect(x: 0, y: frame.size.height - thickness, width: frame.size.width, height: thickness)
            case .Left:
                border.frame = CGRect(x: 0, y: 0, width: thickness, height: frame.size.height)
            case .Right:
                border.frame = CGRect(x: frame.size.width - thickness, y: 0, width: thickness, height: frame.size.height)
            }
    
            layer.addSublayer(border)
        }
    }
    

    为了设置相应的边框,你应该重写 viewDidLayoutSubviews() 方法:

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        yourView.addBorder(toSide: UIView.ViewSide.Top, withColor: UIColor.lightGray, andThickness: 1)
    

    【讨论】:

    • 每当布局更新时它会调用'addSublayer'吗?
    【解决方案6】:

    对我有用

    extension UIView {
    
        func addBorders(edges: UIRectEdge = .all, color: UIColor = .black, width: CGFloat = 1.0) {
    
            func createBorder() -> UIView {
                let borderView = UIView(frame: CGRect.zero)
                borderView.translatesAutoresizingMaskIntoConstraints = false
                borderView.backgroundColor = color
                return borderView
            }
    
            if (edges.contains(.all) || edges.contains(.top)) {
                let topBorder = createBorder()
                self.addSubview(topBorder)
                NSLayoutConstraint.activate([
                    topBorder.topAnchor.constraint(equalTo: self.topAnchor),
                    topBorder.leadingAnchor.constraint(equalTo: self.leadingAnchor),
                    topBorder.trailingAnchor.constraint(equalTo: self.trailingAnchor),
                    topBorder.heightAnchor.constraint(equalToConstant: width)
                    ])
            }
            if (edges.contains(.all) || edges.contains(.left)) {
                let leftBorder = createBorder()
                self.addSubview(leftBorder)
                NSLayoutConstraint.activate([
                    leftBorder.topAnchor.constraint(equalTo: self.topAnchor),
                    leftBorder.bottomAnchor.constraint(equalTo: self.bottomAnchor),
                    leftBorder.leadingAnchor.constraint(equalTo: self.leadingAnchor),
                    leftBorder.widthAnchor.constraint(equalToConstant: width)
                    ])
            }
            if (edges.contains(.all) || edges.contains(.right)) {
                let rightBorder = createBorder()
                self.addSubview(rightBorder)
                NSLayoutConstraint.activate([
                    rightBorder.topAnchor.constraint(equalTo: self.topAnchor),
                    rightBorder.bottomAnchor.constraint(equalTo: self.bottomAnchor),
                    rightBorder.trailingAnchor.constraint(equalTo: self.trailingAnchor),
                    rightBorder.widthAnchor.constraint(equalToConstant: width)
                    ])
            }
            if (edges.contains(.all) || edges.contains(.bottom)) {
                let bottomBorder = createBorder()
                self.addSubview(bottomBorder)
                NSLayoutConstraint.activate([
                    bottomBorder.bottomAnchor.constraint(equalTo: self.bottomAnchor),
                    bottomBorder.leadingAnchor.constraint(equalTo: self.leadingAnchor),
                    bottomBorder.trailingAnchor.constraint(equalTo: self.trailingAnchor),
                    bottomBorder.heightAnchor.constraint(equalToConstant: width)
                    ])
            }
        }
    }
    

    【讨论】:

      【解决方案7】:

      这是一个简单的解决方案。在UIView 上添加标签,清除标签上的文本并将标签背景颜色设置为边框颜色。将标签的原点(x,y) 设置为视图的原点(x,y)。并将标签的宽度设置为UIView 的宽度,将高度设置为 1 或 2(用于UIView 顶部的边框高度)。这应该可以解决问题。

      【讨论】:

      • 那么没有标签的意义,还不如只是另一个UIView
      • 这并不能真正回答仅将顶部边框添加到 uiview 的问题。这是一个快速修复,可能不适用于更复杂的问题。
      【解决方案8】:

      我想出了一个使用Swift 4.1 的解决方案,它使用AutoLayoutUIViews,以便它可以随视图调整大小。

      它基于@AdamWaite 的回答,但解决了重复使用单元格的表格视图单元格的问题。如果在添加新边框之前没有删除之前的边框,那么重用的单元格将包含多个边框。

      这可以通过创建一个虚拟 BorderView 类并在子视图中搜索边框并删除它们来解决。

      此代码使用SnapKit 进行约束,使用CocoaLumberjack 进行调试。如果您不使用这些,那么转换应该相当简单

      class BorderView: UIView {
      }
      
      extension UIView {
          private func addSidedBorder(toEdge edge: UIRectEdge, withColor color: UIColor, inset: CGFloat, thickness: CGFloat) {
              let border = BorderView(frame: .zero)
              border.backgroundColor = color
              addSubview(border)
      
              border.snp.makeConstraints { make in
                  switch edge {
                  case .top:
                      make.top.equalToSuperview()
                      make.height.equalTo(thickness)
                      make.left.right.equalToSuperview().inset(inset)
      
                  case .left:
                      make.left.equalToSuperview()
                      make.width.equalTo(thickness)
                      make.top.bottom.equalToSuperview().inset(inset)
      
                  case .bottom:
                      make.bottom.equalToSuperview()
                      make.height.equalTo(thickness)
                      make.left.right.equalToSuperview().inset(inset)
      
                  case .right:
                      make.right.equalToSuperview()
                      make.width.equalTo(thickness)
                      make.top.bottom.equalToSuperview().inset(inset)
      
                  default:
                      DDLogWarn("Invalid sided border given in ExtendedUIView, border not added correctly")
                  }
              }
          }
      
          func addBorder(toEdge edge: UIRectEdge, withColor color: UIColor = .black, inset: CGFloat = 0.0, thickness: CGFloat = 1.0) {
              // Remove existing borders from view and readd them
              for view in subviews {
                  if view is BorderView {
                      view.removeFromSuperview()
                  }
              }
      
              if edge.contains(.all) {
                  addSidedBorder(toEdge: .top, withColor: color, inset: inset, thickness: thickness)
                  addSidedBorder(toEdge: .left, withColor: color, inset: inset, thickness: thickness)
                  addSidedBorder(toEdge: .bottom, withColor: color, inset: inset, thickness: thickness)
                  addSidedBorder(toEdge: .right, withColor: color, inset: inset, thickness: thickness)
              } else {
                  if edge.contains(.top) {
                      addSidedBorder(toEdge: .top, withColor: color, inset: inset, thickness: thickness)
                  }
      
                  if edge.contains(.left) {
                      addSidedBorder(toEdge: .left, withColor: color, inset: inset, thickness: thickness)
                  }
      
                  if edge.contains(.bottom) {
                      addSidedBorder(toEdge: .bottom, withColor: color, inset: inset, thickness: thickness)
                  }
      
                  if edge.contains(.right) {
                      addSidedBorder(toEdge: .right, withColor: color, inset: inset, thickness: thickness)
                  }
              }
          }
      }
      

      添加此代码,然后在子类UIView 中调用:

      view.addBorder(toEdge: [.left, .right], withColor: .red, inset: 0.0, thickness: 1.0)
      

      【讨论】:

      • 这个答案很好,很好地解决了重绘边框的问题。但是,BorderView 虚拟类应标记为 fileprivate,因为它只能在此扩展程序中访问。
      • BorderView有什么用?我猜你可以直接使用 UIView 作为分隔符。
      • 并非完全必要,但我使用它在添加新边框之前删除视图中的任何现有边框。防止向视图添加多个边框。
      【解决方案9】:

      如果我从情节提要中构建,我更喜欢在有用的UIView 后面添加一个UIView...如果我想在我的UIView 顶部创建一个边框,我只需增加高度背景UIView 由我的边框宽度.. 任何其他边都可以这样做:)

      【讨论】:

        【解决方案10】:
        extension UIView {
        
            func addBorder(edge: UIRectEdge, color: UIColor, borderWidth: CGFloat) {
        
                let seperator = UIView()
                self.addSubview(seperator)
                seperator.translatesAutoresizingMaskIntoConstraints = false
        
                seperator.backgroundColor = color
        
                if edge == .top || edge == .bottom
                {
                    seperator.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
                    seperator.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
                    seperator.heightAnchor.constraint(equalToConstant: borderWidth).isActive = true
        
                    if edge == .top
                    {
                        seperator.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
                    }
                    else
                    {
                        seperator.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
                    }
                }
                else if edge == .left || edge == .right
                {
                    seperator.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
                    seperator.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
                    seperator.widthAnchor.constraint(equalToConstant: borderWidth).isActive = true
        
                    if edge == .left
                    {
                        seperator.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
                    }
                    else
                    {
                        seperator.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
                    }
                }
            }
        
        }
        

        【讨论】:

          【解决方案11】:

          受@Addison 的启发,我在不使用任何第三方框架的情况下重写了扩展,因为他使用了 SnapKit 和 CocoaLumberjack。

          与@Addisons 方法一样,我还删除了以前添加的边框,因此该实现应该与可重用视图作为表格单元格和集合单元格一起使用。

          fileprivate class BorderView: UIView {} // dummy class to help us differentiate among border views and other views
                                                  // to enabling us to remove existing borders and place new ones
          
          extension UIView {
          
              func setBorders(toEdges edges: [UIRectEdge], withColor color: UIColor, inset: CGFloat = 0, thickness: CGFloat) {
                  // Remove existing edges
                  for view in subviews {
                      if view is BorderView {
                          view.removeFromSuperview()
                      }
                  }
                  // Add new edges
                  if edges.contains(.all) {
                      addSidedBorder(toEdge: [.left,.right, .top, .bottom], withColor: color, inset: inset, thickness: thickness)
                  }
                  if edges.contains(.left) {
                      addSidedBorder(toEdge: [.left], withColor: color, inset: inset, thickness: thickness)
                  }
                  if edges.contains(.right) {
                      addSidedBorder(toEdge: [.right], withColor: color, inset: inset, thickness: thickness)
                  }
                  if edges.contains(.top) {
                      addSidedBorder(toEdge: [.top], withColor: color, inset: inset, thickness: thickness)
                  }
                  if edges.contains(.bottom) {
                      addSidedBorder(toEdge: [.bottom], withColor: color, inset: inset, thickness: thickness)
                  }
              }
          
              private func addSidedBorder(toEdge edges: [RectangularEdges], withColor color: UIColor, inset: CGFloat = 0, thickness: CGFloat) {
                  for edge in edges {
                      let border = BorderView(frame: .zero)
                      border.backgroundColor = color
                      addSubview(border)
                      border.translatesAutoresizingMaskIntoConstraints = false
                      switch edge {
                      case .left:
                          NSLayoutConstraint.activate([
                          border.leftAnchor.constraint(equalTo: self.leftAnchor, constant: inset),
                              border.topAnchor.constraint(equalTo: self.topAnchor, constant: inset),
                              border.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -inset),
                              NSLayoutConstraint(item: border, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: thickness) ])
                      case .right:
                          NSLayoutConstraint.activate([
                              border.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -inset),
                              border.topAnchor.constraint(equalTo: self.topAnchor, constant: inset),
                              border.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -inset),
                              NSLayoutConstraint(item: border, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: thickness) ])
                      case .top:
                          NSLayoutConstraint.activate([
                              border.leftAnchor.constraint(equalTo: self.leftAnchor, constant: inset),
                              border.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -inset),
                              border.topAnchor.constraint(equalTo: self.topAnchor, constant: inset),
                              NSLayoutConstraint(item: border, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: thickness) ])
                      case .bottom:
                          NSLayoutConstraint.activate([
                              border.leftAnchor.constraint(equalTo: self.leftAnchor, constant: inset),
                              border.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -inset),
                              border.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -inset),
                              NSLayoutConstraint(item: border, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: thickness) ])
                      }
                  }
              }
          
              private enum RectangularEdges {
                  case left
                  case right
                  case top
                  case bottom
              }
          }
          

          【讨论】:

            【解决方案12】:

            子类UIView 并在您的子类中实现drawRect:,例如:

            Objective-c

            - (void)drawRect:(CGRect)rect {
                CGContextRef context = UIGraphicsGetCurrentContext();
                CGContextMoveToPoint(context, CGRectGetMinX(rect), CGRectGetMinY(rect));
                CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMinY(rect));
                CGContextSetStrokeColorWithColor(context, [[UIColor redColor] CGColor] );
                CGContextSetLineWidth(context, 2.0);
                CGContextStrokePath(context);
            }
            

            斯威夫特 4

            override func draw(_ rect: CGRect) {
            
                let cgContext = UIGraphicsGetCurrentContext()
                cgContext?.move(to: CGPoint(x: rect.minX, y: rect.minY))
                cgContext?.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
                cgContext?.setStrokeColor(UIColor.red.cgColor)
                cgContext?.setLineWidth(2.0)
                cgContext?.strokePath()
            }
            

            这会绘制一条 2 像素的红线作为上边框。您提到的所有其他变体都留给读者做一个简单的练习。

            推荐Quartz 2D Programming Guide

            【讨论】:

            • 这是唯一的方法吗???因此,如果我需要创建一个带有顶部边框的视图,以及带有底部边框的其他视图,以及其他视图......我的意思总是一个带有一个或两个边框的特定视图,我将不得不为每个特定情况创建一个子类???我不知道仅仅为了添加边框而创建类是否真的很好......
            • 没有。想想看。您的UIView 子类可以有一个属性来确定drawRect: 绘制的边框。可以使用NS_OPTIONS 定义此属性,以便它定义一个位掩码,如UIViewAutoresizing 位掩码。如果 - 无论出于何种原因 - 你真的强烈反对子类化 UIView 然后只需添加一个 1-2 像素高(或宽)的小子视图,并给它任何你想要模拟边框的尺寸。
            • 大家好,我根据这段代码制作了一个 Swift 子类,希望你喜欢它:gist.github.com/asiviero/4f52ab7dea7d9252a64c
            【解决方案13】:

            我考虑在这里继承 UIView 并覆盖 drawRect 过度杀伤力。为什么不在UIView 上添加扩展并添加边框子视图?

            @discardableResult
            func addBorders(edges: UIRectEdge,
                            color: UIColor,
                            inset: CGFloat = 0.0,
                            thickness: CGFloat = 1.0) -> [UIView] {
            
                var borders = [UIView]()
            
                @discardableResult
                func addBorder(formats: String...) -> UIView {
                    let border = UIView(frame: .zero)
                    border.backgroundColor = color
                    border.translatesAutoresizingMaskIntoConstraints = false
                    addSubview(border)
                    addConstraints(formats.flatMap {
                        NSLayoutConstraint.constraints(withVisualFormat: $0,
                                                       options: [],
                                                       metrics: ["inset": inset, "thickness": thickness],
                                                       views: ["border": border]) })
                    borders.append(border)
                    return border
                }
            
            
                if edges.contains(.top) || edges.contains(.all) {
                    addBorder(formats: "V:|-0-[border(==thickness)]", "H:|-inset-[border]-inset-|")
                }
            
                if edges.contains(.bottom) || edges.contains(.all) {
                    addBorder(formats: "V:[border(==thickness)]-0-|", "H:|-inset-[border]-inset-|")
                }
            
                if edges.contains(.left) || edges.contains(.all) {
                    addBorder(formats: "V:|-inset-[border]-inset-|", "H:|-0-[border(==thickness)]")
                }
            
                if edges.contains(.right) || edges.contains(.all) {
                    addBorder(formats: "V:|-inset-[border]-inset-|", "H:[border(==thickness)]-0-|")
                }
            
                return borders
            }
            
                // Usage:         
                view.addBorder(edges: [.all]) // All with default arguments 
                view.addBorder(edges: [.top], color: .green) // Just Top, green, default thickness
                view.addBorder(edges: [.left, .right, .bottom], color: .red, thickness: 3) // All except Top, red, thickness 3
            

            使用此代码,您也不必绑定到您的子类,您可以将其应用于从UIView 继承的任何事物和所有事物 - 可在您的项目和任何其他项目中重用。将其他参数传递给您的方法以定义其他颜色和宽度。很多选择。

            【讨论】:

            • 这里唯一的缺点是它不能调整大小。
            • 可以使用 UIView 并添加自动布局约束。原理相同。
            • @PeterDeWeese 这也不是一个缺点 - 如果你想控制边框的大小,你需要做的就是: - (void)addUpperBorderWithSize:(CGFloat)size 然后用函数中的参数替换常量。颜色等其他参数也是如此。
            • @AdamWaite ,这个自动布局变体看起来很不错。谢谢!
            • 感谢分享,我做了一个带有自动布局约束here的Objective-C版本。
            【解决方案14】:

            我对@9​​87654321@ 进行了一些更改,以便我可以使用一个命令为多个边缘添加边框:

            infoView.addBorder(toEdges: [.left, .bottom, .right], color: borderColor, thickness: 1)
            

            这是完整的代码:

            extension UIView {
                func addBorder(toEdges edges: UIRectEdge, color: UIColor, thickness: CGFloat) {
            
                    func addBorder(toEdge edges: UIRectEdge, color: UIColor, thickness: CGFloat) {
                        let border = CALayer()
                        border.backgroundColor = color.cgColor
            
                        switch edges {
                        case .top:
                            border.frame = CGRect(x: 0, y: 0, width: frame.width, height: thickness)
                        case .bottom:
                            border.frame = CGRect(x: 0, y: frame.height - thickness, width: frame.width, height: thickness)
                        case .left:
                            border.frame = CGRect(x: 0, y: 0, width: thickness, height: frame.height)
                        case .right:
                            border.frame = CGRect(x: frame.width - thickness, y: 0, width: thickness, height: frame.height)
                        default:
                            break
                        }
            
                        layer.addSublayer(border)
                    }
            
                    if edges.contains(.top) || edges.contains(.all) {
                        addBorder(toEdge: .top, color: color, thickness: thickness)
                    }
            
                    if edges.contains(.bottom) || edges.contains(.all) {
                        addBorder(toEdge: .bottom, color: color, thickness: thickness)
                    }
            
                    if edges.contains(.left) || edges.contains(.all) {
                        addBorder(toEdge: .left, color: color, thickness: thickness)
                    }
            
                    if edges.contains(.right) || edges.contains(.all) {
                        addBorder(toEdge: .right, color: color, thickness: thickness)
                    }
                }
            }
            

            【讨论】:

              【解决方案15】:

              这是Pauls's answer 的 Swift 4 版本

              func addTopBorder(color: UIColor, thickness: CGFloat) {
                  let border = UIView()
                  border.backgroundColor = color
                  border.autoresizingMask = [.flexibleWidth, .flexibleBottomMargin]
                  border.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: thickness)
                  addSubview(border)
              }
              
              func addBottomBorder(color: UIColor, thickness: CGFloat) {
                  let border = UIView()
                  border.backgroundColor = color
                  border.autoresizingMask = [.flexibleWidth, .flexibleTopMargin]
                  border.frame = CGRect(x: 0, y: frame.size.height - thickness, width: frame.size.width, height: thickness)
                  addSubview(border)
              }
              
              func addLeftBorder(color: UIColor, thickness: CGFloat) {
                  let border = UIView()
                  border.backgroundColor = color
                  border.autoresizingMask = [.flexibleHeight, .flexibleRightMargin]
                  border.frame = CGRect(x: 0, y: 0, width: thickness, height: frame.size.height)
                  addSubview(border)
              }
              
              func addRightBorder(color: UIColor, thickness: CGFloat) {
                  let border = UIView()
                  border.backgroundColor = color
                  border.autoresizingMask = [.flexibleHeight, .flexibleLeftMargin]
                  border.frame = CGRect(x: frame.size.width - thickness, y: 0, width: thickness, height: frame.size.height)
                  addSubview(border)
              }
              

              【讨论】:

                【解决方案16】:

                在 Swift 4 和 3 中

                let borderThickness = 2
                let topBorder = UIView()
                topBorder.backgroundColor = UIColor.red
                topBorder.frame = CGRect(x: 0, y: 0, width: 
                                  Int(yourViewFromOutlet.frame.size.width), height: 
                                  borderThickness)
                yourViewFromOutlet.addSubview(topBorder)
                

                【讨论】:

                  【解决方案17】:

                  用于在 Swift 中为 UIView 设置上边框和下边框。

                  let topBorder = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 1))
                  topBorder.backgroundColor = UIColor.black
                  myView.addSubview(topBorder)
                  
                  let bottomBorder = UIView(frame: CGRect(x: 0, y: myView.frame.size.height - 1, width: 10, height: 1))
                  bottomBorder.backgroundColor = UIColor.black
                  myView.addSubview(bottomBorder)
                  

                  【讨论】:

                    【解决方案18】:

                    //MARK:- 为视图添加左边框

                    (void)prefix_addLeftBorder:(UIView *) viewName
                    {
                        CALayer *leftBorder = [CALayer layer];
                        leftBorder.backgroundColor = [UIColor colorWithRed:221/255.0f green:221/255.0f blue:221/255.0f alpha:1.0f].CGColor;
                        leftBorder.frame = CGRectMake(0,0,1.0,viewName.frame.size.height);
                        [viewName.layer addSublayer:leftBorder];
                    }
                    

                    //MARK:- 为视图添加右边框

                    (void)prefix_addRightBorder:(UIView *) viewName
                    {
                        CALayer *rightBorder = [CALayer layer];
                        rightBorder.backgroundColor = [UIColor colorWithRed:221/255.0f green:221/255.0f blue:221/255.0f alpha:1.0f].CGColor;
                        rightBorder.frame = CGRectMake(viewName.frame.size.width - 1.0,0,1.0,viewName.frame.size.height);
                        [viewName.layer addSublayer:rightBorder];
                    }
                    

                    //MARK:- 为视图添加底部边框

                    (void)prefix_addbottomBorder:(UIView *) viewName
                    {
                        CALayer *bottomBorder = [CALayer layer];
                        bottomBorder.backgroundColor = [UIColor colorWithRed:221/255.0f green:221/255.0f blue:221/255.0f alpha:1.0f].CGColor;
                        bottomBorder.frame = CGRectMake(0,viewName.frame.size.height - 1.0,viewName.frame.size.width,1.0);
                        [viewName.layer addSublayer:bottomBorder];
                    }
                    

                    【讨论】:

                      【解决方案19】:

                      如果有人需要 Xamarin 版本:

                      public static class UIUtils
                      {
                          public static void AddBorder(this CALayer cALayer, UIRectEdge edge, UIColor color, float thickness)
                          {
                      
                              var border = new CALayer();
                              switch (edge) 
                              {
                                  case UIRectEdge.Top:
                                      border.Frame = new CGRect(0, 0, cALayer.Frame.Width, height: thickness);
                                      break;
                                  case UIRectEdge.Bottom:
                                      border.Frame = new CGRect(0, cALayer.Frame.Height - thickness, width: cALayer.Frame.Width, height: thickness);
                                      break;
                                  case UIRectEdge.Left:
                                      border.Frame = new CGRect(0, 0, width: thickness, height: cALayer.Frame.Height);
                                      break;
                                  case UIRectEdge.Right:
                                      border.Frame = new CGRect(cALayer.Frame.Width - thickness, y: 0, width: thickness, height: cALayer.Frame.Height);
                                      break;
                                  default: break;
                              }
                              border.BackgroundColor = color.CGColor;
                              cALayer.AddSublayer(border);
                          }
                      }
                      

                      【讨论】:

                        【解决方案20】:

                        注意:这里的大多数解决方案都不是自适应的,也不会调整大小。将调整大小的解决方案将对您的启动时间产生巨大影响,因为它们使用大量 CPU。

                        您可以在下面使用此解决方案。它适用于比层更轻的 UIBezierPaths,从而导致快速启动时间。它易于使用,请参阅下面的说明。

                        class ResizeBorderView: UIView {
                            var color = UIColor.white
                            var lineWidth: CGFloat = 1
                            var edges = [UIRectEdge](){
                                didSet {
                                    setNeedsDisplay()
                                }
                            }
                            override func draw(_ rect: CGRect) {
                                if edges.contains(.top) || edges.contains(.all){
                                    let path = UIBezierPath()
                                    path.lineWidth = lineWidth
                                    color.setStroke()
                                    UIColor.blue.setFill()
                                    path.move(to: CGPoint(x: 0, y: 0 + lineWidth / 2))
                                    path.addLine(to: CGPoint(x: self.bounds.width, y: 0 + lineWidth / 2))
                                    path.stroke()
                                }
                                if edges.contains(.bottom) || edges.contains(.all){
                                    let path = UIBezierPath()
                                    path.lineWidth = lineWidth
                                    color.setStroke()
                                    UIColor.blue.setFill()
                                    path.move(to: CGPoint(x: 0, y: self.bounds.height - lineWidth / 2))
                                    path.addLine(to: CGPoint(x: self.bounds.width, y: self.bounds.height - lineWidth / 2))
                                    path.stroke()
                                }
                                if edges.contains(.left) || edges.contains(.all){
                                    let path = UIBezierPath()
                                    path.lineWidth = lineWidth
                                    color.setStroke()
                                    UIColor.blue.setFill()
                                    path.move(to: CGPoint(x: 0 + lineWidth / 2, y: 0))
                                    path.addLine(to: CGPoint(x: 0 + lineWidth / 2, y: self.bounds.height))
                                    path.stroke()
                                }
                                if edges.contains(.right) || edges.contains(.all){
                                    let path = UIBezierPath()
                                    path.lineWidth = lineWidth
                                    color.setStroke()
                                    UIColor.blue.setFill()
                                    path.move(to: CGPoint(x: self.bounds.width - lineWidth / 2, y: 0))
                                    path.addLine(to: CGPoint(x: self.bounds.width - lineWidth / 2, y: self.bounds.height))
                                    path.stroke()
                                }
                            }
                        }
                        
                        1. 将 UIView 的类设置为 ResizeBorderView
                        2. 在 viewDidAppear 方法中使用 yourview.color 和 yourview.lineWidth 设置颜色和线宽
                        3. 设置边缘,例如:yourview.edges = [.right, .left] ([.all]) for all
                        4. 享受快速启动和调整边框大小

                        【讨论】:

                          【解决方案21】:

                          您还可以查看这个 UIKit 和 Foundation 类别的集合:https://github.com/leszek-s/LSCategories

                          它允许使用单行代码在 UIView 的一侧添加边框:

                          [self.someView lsAddBorderOnEdge:UIRectEdgeTop color:[UIColor blueColor] width:2];
                          

                          它可以正确处理视图旋转,而这里发布的大多数答案都不能很好地处理它。

                          【讨论】:

                            【解决方案22】:

                            老问题,但仍然缺少运行时边界调整的自动布局解决方案。

                            borders(for: [.left, .bottom], width: 2, color: .red)
                            

                            以下 UIView 扩展将仅在给定边缘添加边框。如果您在运行时更改边缘,则边框将相应调整。

                            extension UIView {
                                func borders(for edges:[UIRectEdge], width:CGFloat = 1, color: UIColor = .black) {
                            
                                    if edges.contains(.all) {
                                        layer.borderWidth = width
                                        layer.borderColor = color.cgColor
                                    } else {
                                        let allSpecificBorders:[UIRectEdge] = [.top, .bottom, .left, .right]
                            
                                        for edge in allSpecificBorders {
                                            if let v = viewWithTag(Int(edge.rawValue)) {
                                                v.removeFromSuperview()
                                            }
                            
                                            if edges.contains(edge) {
                                                let v = UIView()
                                                v.tag = Int(edge.rawValue)
                                                v.backgroundColor = color
                                                v.translatesAutoresizingMaskIntoConstraints = false
                                                addSubview(v)
                            
                                                var horizontalVisualFormat = "H:"
                                                var verticalVisualFormat = "V:"
                            
                                                switch edge {
                                                case UIRectEdge.bottom:
                                                    horizontalVisualFormat += "|-(0)-[v]-(0)-|"
                                                    verticalVisualFormat += "[v(\(width))]-(0)-|"
                                                case UIRectEdge.top:
                                                    horizontalVisualFormat += "|-(0)-[v]-(0)-|"
                                                    verticalVisualFormat += "|-(0)-[v(\(width))]"
                                                case UIRectEdge.left:
                                                    horizontalVisualFormat += "|-(0)-[v(\(width))]"
                                                    verticalVisualFormat += "|-(0)-[v]-(0)-|"
                                                case UIRectEdge.right:
                                                    horizontalVisualFormat += "[v(\(width))]-(0)-|"
                                                    verticalVisualFormat += "|-(0)-[v]-(0)-|"
                                                default:
                                                    break
                                                }
                            
                                                self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: horizontalVisualFormat, options: .directionLeadingToTrailing, metrics: nil, views: ["v": v]))
                                                self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: verticalVisualFormat, options: .directionLeadingToTrailing, metrics: nil, views: ["v": v]))
                                            }
                                        }
                                    }
                                }
                            }
                            

                            【讨论】:

                              【解决方案23】:

                              对于 C# 中的 Xamarin,我只是在添加子层时创建内联边框

                                View.Layer.AddSublayer(new CALayer()
                                  {
                                      BackgroundColor = UIColor.Black.CGColor,
                                      Frame = new CGRect(0, 0, View.Frame.Width, 0.5f)
                                  });
                              

                              您可以(根据其他人的建议)为底部、左侧和右侧边框安排此设置。

                              【讨论】:

                                【解决方案24】:

                                DanShev 答案转换为 Swift 3

                                extension CALayer {
                                
                                func addBorder(edge: UIRectEdge, color: UIColor, thickness: CGFloat) {
                                
                                    let border = CALayer()
                                
                                    switch edge {
                                    case .top:
                                        border.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: thickness)
                                        break
                                    case .bottom:
                                        border.frame = CGRect(x: 0, y: self.frame.height - thickness, width: self.frame.width, height: thickness)
                                        break
                                    case .left:
                                        border.frame = CGRect(x: 0, y: 0, width: thickness, height: self.frame.height)
                                        break
                                    case .right:
                                        border.frame = CGRect(x: self.frame.width - thickness, y: 0, width: thickness, height: self.frame.height)
                                        break
                                    default:
                                        break
                                    }
                                
                                    border.backgroundColor = color.cgColor;
                                
                                    self.addSublayer(border)
                                }
                                }
                                

                                【讨论】:

                                  【解决方案25】:

                                  所选答案的代码,以防万一。

                                  注意:这不适用于自动布局(也就是将设备旋转到横向等)。

                                  首先定义一个厚度:

                                  NSInteger borderThickness = 1;
                                  

                                  然后只需复制使用其中任何一个或所有这些来设置您要设置的边框。

                                  顶部边框

                                  UIView *topBorder = [UIView new];
                                  topBorder.backgroundColor = [UIColor lightGrayColor];
                                  topBorder.frame = CGRectMake(0, 0, myView.frame.size.width, borderThickness);
                                  [myView addSubview:topBorder];
                                  

                                  底部边框

                                  UIView *bottomBorder = [UIView new];
                                  bottomBorder.backgroundColor = [UIColor lightGrayColor];
                                  bottomBorder.frame = CGRectMake(0, myView.frame.size.height - borderThickness, myView.frame.size.width, borderThickness);
                                  [myView addSubview:bottomBorder];
                                  

                                  左边框

                                  UIView *leftBorder = [UIView new];
                                  leftBorder.backgroundColor = [UIColor lightGrayColor];
                                  leftBorder.frame = CGRectMake(0, 0, borderThickness, myView.frame.size.height);
                                  [myView addSubview:leftBorder];
                                  

                                  右边框

                                  UIView *rightBorder = [UIView new];
                                  rightBorder.backgroundColor = [UIColor lightGrayColor];
                                  rightBorder.frame = CGRectMake(myView.frame.size.width - borderThickness, 0, borderThickness, myView.frame.size.height);
                                  [myView addSubview:rightBorder];
                                  

                                  【讨论】:

                                  • 非常简单的解决方案...与裸 CALayer 相比,UIView 开销更大
                                  • 在阅读了所有其他解决方案之后,我想我也只需添加一个小视图。所有这些都适用于边界!该解决方案也只需要几个引脚即可在自动布局中工作。更容易理解。
                                  • 谢谢,我在上面添加了一条注释,以便编码人员只有在他们的应用程序不旋转时才能使用。
                                  【解决方案26】:

                                  只是在这里发布以帮助寻找添加边框的人。我在这里swift label only border left 对接受的答案进行了一些更改。 将UIRectEdge.Top 的宽度从CGRectGetHeight(self.frame) 更改为CGRectGetWidth(self.frame),将UIRectEdge.BottomUIScreen.mainScreen().bounds.width 更改为CGRectGetWidth(self.frame) 以正确获取边框。使用 Swift 2。

                                  最后的扩展是:

                                  extension CALayer {
                                  
                                  func addBorder(edge: UIRectEdge, color: UIColor, thickness: CGFloat) {
                                  
                                      let border = CALayer();
                                  
                                      switch edge {
                                      case UIRectEdge.Top:
                                          border.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), thickness); 
                                          break
                                      case UIRectEdge.Bottom:
                                          border.frame = CGRectMake(0, CGRectGetHeight(self.frame) - thickness, CGRectGetWidth(self.frame), thickness)
                                          break
                                      case UIRectEdge.Left:
                                          border.frame = CGRectMake(0, 0, thickness, CGRectGetHeight(self.frame))
                                          break
                                      case UIRectEdge.Right:
                                          border.frame = CGRectMake(CGRectGetWidth(self.frame) - thickness, 0, thickness, CGRectGetHeight(self.frame))
                                          break
                                      default:
                                          break
                                      }
                                  
                                      border.backgroundColor = color.CGColor;
                                  
                                      self.addSublayer(border)
                                  }
                                  
                                  }
                                  

                                  【讨论】:

                                    【解决方案27】:

                                    Swift 版本:

                                    var myView = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
                                    myView.backgroundColor = UIColor.yellowColor() 
                                    
                                    var border = CALayer()
                                    border.backgroundColor = UIColor.lightGrayColor()
                                    border.frame = CGRect(x: 0, y: 0, width: myView.frame.width, height: 0.5)
                                    
                                    myView.layer.addSublayer(border)
                                    

                                    编辑:有关更新版本,请在此处查看我的仓库: https://github.com/goktugyil/EZSwiftExtensions/blob/master/Sources/UIViewExtensions.swift

                                    查看 addBorder 部分

                                    【讨论】:

                                      【解决方案28】:

                                      除了n8tr 之外,还可以添加从情节提要中设置它们的可用性:
                                      - 在 .h 文件中添加两个属性,如 borderColorborderWidth
                                      - 然后你可以在情节提要中添加keyPaths,请参阅screenshot的链接

                                      【讨论】:

                                        【解决方案29】:

                                        我接受了 Adam Waite 和 Pauls 的答案并将它们结合起来。我还添加了将所选边缘连接在一起的可能性,因此您只需调用一个函数,如下所示:

                                        [self.view addBordersToEdge:(UIRectEdgeLeft|UIRectEdgeRight)
                                                          withColor:[UIColor grayColor]
                                                           andWidth:1.0];
                                        

                                        左右:

                                        [self.view addBordersToEdge:(UIRectEdgeAll)
                                                          withColor:[UIColor grayColor]
                                                           andWidth:1.0];
                                        

                                        您需要实现的是 UIView 上的一个类别,如其他答案中建议的那样,具有以下实现:

                                        - (void)addBordersToEdge:(UIRectEdge)edge withColor:(UIColor *)color andWidth:(CGFloat) borderWidth {
                                            if (edge & UIRectEdgeTop) {
                                                UIView *border = [UIView new];
                                                border.backgroundColor = color;
                                                [border setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin];
                                                border.frame = CGRectMake(0, 0, self.frame.size.width, borderWidth);
                                                [self addSubview:border];
                                            }
                                        
                                            if (edge & UIRectEdgeLeft) {
                                                UIView *border = [UIView new];
                                                border.backgroundColor = color;
                                                border.frame = CGRectMake(0, 0, borderWidth, self.frame.size.height);
                                                [border setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleRightMargin];
                                                [self addSubview:border];
                                            }
                                        
                                            if (edge & UIRectEdgeBottom) {
                                                UIView *border = [UIView new];
                                                border.backgroundColor = color;
                                                [border setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin];
                                                border.frame = CGRectMake(0, self.frame.size.height - borderWidth, self.frame.size.width, borderWidth);
                                                [self addSubview:border];
                                            }
                                        
                                            if (edge & UIRectEdgeRight) {
                                                UIView *border = [UIView new];
                                                border.backgroundColor = color;
                                                [border setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin];
                                                border.frame = CGRectMake(self.frame.size.width - borderWidth, 0, borderWidth, self.frame.size.height);
                                                [self addSubview:border];
                                            }
                                        }
                                        

                                        【讨论】:

                                          【解决方案30】:

                                          我对类似问题的回答:https://stackoverflow.com/a/27141956/435766 我个人更喜欢在那个类别上走下去,因为我希望能够在 UIView 的任何子类上使用它。

                                          【讨论】:

                                            猜你喜欢
                                            • 1970-01-01
                                            • 2013-07-10
                                            • 1970-01-01
                                            • 1970-01-01
                                            • 1970-01-01
                                            • 2014-07-30
                                            • 1970-01-01
                                            • 2017-12-20
                                            • 2011-10-01
                                            相关资源
                                            最近更新 更多