programing

UI 보기의 맨 위에 테두리를 추가하는 방법

closeapi 2023. 4. 26. 23:21
반응형

UI 보기의 맨 위에 테두리를 추가하는 방법

제 질문은 제목에 있습니다.

위쪽이든 아래쪽이든 특정 면에 테두리를 추가하는 방법을 모르겠습니다. layer.border전체 뷰의 경계를 그립니다...

는 서브클래스 분류고다니합려를하위class▁sub다▁considering▁i니를 고려합니다.UIView 및우위순선iding를 재정의함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사용자의 프로젝트 및 기타 모든 항목에서 재사용할 수 있습니다.다른 색상과 너비를 정의하기 위해 다른 인수를 방법에 전달합니다.다양한 옵션.

Adam Waite의 원래 게시물에 둥근 모서리에 대한 기능 추가 및 다중 편집

중요!:이전에 언급한 대로 'add border'를 호출하기 직전에 'label.layoutIfNeeded()'를 추가하는 것을 잊지 마십시오.

참고: UILabel에서만 테스트했습니다.

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

이지만, UIView에 있는 카테고리입니다.adding views CALayers, 즉 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)
}

스위프트 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)
 }
}

클래스UIView을 구현합니다.drawRect:하위 클래스에서 예:

목표-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 프로그래밍 가이드를 권장합니다.

원하는 사용자가 있을 경우 선택한 답변의 코드입니다.

참고: 이는 자동 레이아웃(예: 장치를 가로 방향으로 회전)에서는 작동하지 않습니다.

먼저 두께를 정의합니다.

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];

이전 질문이지만 런타임 테두리 조정이 있는 자동 레이아웃 솔루션이 여전히 없습니다.

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

빠른 버전:

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

경계 부분 추가를 확인합니다.

Swift 4.2 및 자동 레이아웃

저는 제안된 해결책을 검토했습니다.대부분이 프레임에 기반을 두고 있습니다. 이는 AutoLayout과 함께 작동하는 간단한 확장입니다. 레이어 대신 View를 사용하여 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
        }
    }
}

아담 웨이트와 폴스의 답변을 모두 받아 조합했습니다.선택한 모서리를 함께 연결할 수 있는 기능도 추가했으므로 다음과 같이 하나의 함수만 호출하면 됩니다.

[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];
    }
}

//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];
}

Dan의 답변을 몇 가지 변경하여 하나의 명령으로 여러 모서리에 테두리를 추가할 수 있었습니다.

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

스위프트 5

편의를 위해 이전 답변 일부 편집 및 추가 방법 추가

import UIKit

extension UIView {
    enum ViewSide {
        case top
        case left
        case bottom
        case right
    }

    func addBorders(to sides: [ViewSide], in color: UIColor, width: CGFloat) {
        sides.forEach { addBorder(to: $0, in: color, width: width) }
    }

    func addBorder(to side: ViewSide, in color: UIColor, width: CGFloat) {
        switch side {
        case .top:
            addTopBorder(in: color, width: width)
        case .left:
            addLeftBorder(in: color, width: width)
        case .bottom:
            addBottomBorder(in: color, width: width)
        case .right:
            addRightBorder(in: color, width: width)
        }
    }

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

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

    func addLeftBorder(in color: UIColor?, width 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(in color: UIColor?, width borderWidth: CGFloat) {
        let border = UIView()
        border.backgroundColor = color
        border.frame = CGRect(x: frame.size.width - borderWidth, y: 0, width: borderWidth, height: frame.size.height)
        border.autoresizingMask = [.flexibleHeight, .flexibleLeftMargin]
        addSubview(border)
    }
}

다음 중 하나를 수행할 수 있습니다.

  1. 특정 방법을 사용하거나 일반 방법을 사용하여 개별적으로 각 테두리 설정, 사례 선택
  2. 테두리 배열 설정

사용 예:

// Adding top border with 2 px in red
let myView = UIView()
myView.addBorder(to: .top, in: .red, width: 2)

(사용 가능한 두 개의 인터페이스에서 오는 모호성을 제거하고 도우미 메소드를 비공개로 설정할 수 있습니다.)저는 그것들을 그곳에서 제거하고 모든 케이스를 주요 방법으로 옮기지 않을 것입니다. 왜냐하면, 제가 보기에, 그것은 그것의 몸을 어지럽힐 수 있기 때문입니다.)

NSBum의 답변을 바탕으로, 저는 비슷한 접근 방식을 취했고 인터페이스 빌더에서 작동하고 제약 조건과 함께 작동하도록 이 간단한 UIView 하위 클래스를 만들었습니다: githublink
CGContextStrokePath 대신 CGContextFillRect를 사용하여 예측 가능하게 선을 완전히 견고하게 유지하고 뷰의 범위 내로 유지할 수 있었습니다.

http://natrosoft.com/ ?p=55에 대한 제 블로그 게시물입니다.

Interface Builder와 UIView는 NAUIViewWithBorders와 함께 사용됩니다.
VC의 는 다음과 같은 합니다.

/* For a top border only ———————————————- */
self.myBorderView.borderColorTop = [UIColor redColor];
self.myBorderView..borderWidthsAll = 1.0f;

/* For borders with different colors and widths ————————— */
self.myBorderView.borderWidths = UIEdgeInsetsMake(2.0, 4.0, 6.0, 8.0);
self.myBorderView.borderColorTop = [UIColor blueColor];
self.myBorderView.borderColorRight = [UIColor redColor];
self.myBorderView.borderColorBottom = [UIColor greenColor];
self.myBorderView.borderColorLeft = [UIColor darkGrayColor];

구현을 확인할 수 있도록 .m 파일에 대한 직접 링크가 있습니다.데모 프로젝트도 있습니다.이것이 누군가에게 도움이 되기를 바랍니다 :)

누군가가 사마린 버전을 필요로 할 경우:

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

비슷한 질문에 대한 저의 대답: https://stackoverflow.com/a/27141956/435766 저는 개인적으로 그것을 UIView의 모든 하위 클래스에서 사용할 수 있기 때문에 카테고리 길을 가는 것을 선호합니다.

C#의 Xamarin의 경우 하위 계층을 추가할 때 경계를 인라인으로 작성합니다.

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

다른 사용자가 제안한 대로 아래쪽, 왼쪽 및 오른쪽 테두리에 대해 이 옵션을 정렬할 수 있습니다.

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

}

스위프트 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)

국경을 추가하려는 사람을 돕기 위해 여기에 게시하는 것입니다.저는 여기서 수락된 답변에 몇 가지 변경을 가했습니다. 라벨만 테두리가 남아 있습니다.케이스의 폭이 변경UIRectEdge.TopCGRectGetHeight(self.frame)CGRectGetWidth(self.frame)그리고 만일의 경우에는UIRectEdge.BottomUIScreen.mainScreen().bounds.widthCGRectGetWidth(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)
}

}

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

여기 폴스의 스위프트 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)
}

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

▁an다▁add니▁if▁from▁prefer선합호▁i것,▁the을을 추가하는 것을 선호합니다.UIView의 유용한 의나유이에면 에.UIView맨 위에 테두리를 작성하려면UIView는 그냥 .UIView내 경계선 폭으로..일 수 :) 른다면도동일게할하수있다습니 :)

여기 간단한 해결책이 있습니다.에레추에 합니다.UIView레이블의 텍스트를 지우고 레이블 배경색을 테두리 색으로 설정합니다.을 설정합니다.(x,y)의 신의라될것다입니이당기원벨.(x,y)당신의 너비로 설정합니다.UIView를 1 의 맨 ).UIView 그리고 그것이 효과가 있을 것입니다.

개인적으로 저는 뷰의 하위 분류 + drawRect를 좋아하지만, 여기 다른 방법이 있습니다(그리고 그것은 @If Pollavith의 승인된 답변과 같은 맥락에서 작동합니다).

새 테두리 레이어는 원하는 치수로 설정할 수 있습니다.@Pollavith의 대답처럼 원하는 높이만큼, 그리고 원하는 시야만큼 넓은 층을 만듭니다.도면층의 프레임 정의를 사용하여 도면층을 원하는 위치에 배치한 다음 뷰에 하위 도면층으로 추가합니다.

참고로, 저만의 요구 사항은 보기의 왼쪽에 테두리를 두는 것이었습니다. (이 코드를 잘라낸 후 붙여넣지 말고 '보기의 맨 위에 테두리를 두지 않기 때문에 아래 코드를 수정하는 것은 매우 간단합니다.)

    CALayer *leftBorder = [CALayer layer];
leftBorder.borderColor = [UIColor colorWithRed:0.0 green:91.0/255.0 blue:141.0/255.0 alpha:1.0].CGColor;
leftBorder.borderWidth = 1;
leftBorder.frame = CGRectMake(0, 0, 1.0, CGRectGetHeight(self.myTargetView.frame));
[self.myTargetView.layer addSublayer:leftBorder];

이에 비해 중간 정도의 이점과 작은 UIBiew 또는 UILabel을 만드는 것은 CALayer가 '경량'이며, CALayer를 사용하는 것과 비교하여 오버라이딩 DrawRect에 대한 많은 흥미로운 견해(의견과 같이)가 있다고 생각합니다(예: iOS: UIBiew의 'DrawRect: 레이어: Context: Context:

애니멀451

저는 파란색을 좋아합니다.

n8tr 외에도 스토리보드에서 설정할 수 있는 기능이 추가될 수 있습니다.
다과같 두가속추가성과 같은 두 가지 합니다.borderColor그리고.borderWidth.h 파일 .h 일파;
그런 다음 추가할 수 있습니다.keyPaths스토리보드에서 스크린샷 링크 참조

다음 UIKit 및 Foundation 범주 모음도 확인할 수 있습니다. https://github.com/leszek-s/LSCategories

코드 한 줄로 UIView의 한 쪽에 테두리를 추가할 수 있습니다.

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

보기 회전을 제대로 처리하지만 여기에 게시된 대부분의 답변은 제대로 처리하지 못합니다.

참고: 대부분의 솔루션은 적응형이 아니며 크기가 조정되지 않습니다.크기를 조정하는 솔루션은 CPU를 많이 사용하기 때문에 시작 시간에 큰 영향을 미칩니다.

아래에 있는 이 솔루션을 사용할 수 있습니다.계층보다 가벼운 UIBeezierPath에서 작동하여 시작 시간이 빠릅니다.사용하기 쉬우므로 아래 지침을 참조하십시오.

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 클래스를 BorderView 크기 조정으로 설정합니다.
  2. view.color와 view.lineWidth를 사용하여 색상과 선폭을 설정합니다.
  3. 모두에 대해 가장자리를 설정합니다. 예: yourview.dll = [.right, .left]([.all])
  4. 빠른 시작 및 테두리 크기 조정

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)

언급URL : https://stackoverflow.com/questions/17355280/how-to-add-a-border-just-on-the-top-side-of-a-uiview

반응형