wake-up-neo.com

So fügen Sie einen Rand direkt auf der Oberseite einer UIView hinzu

Meine Frage bezieht sich auf den Titel.

Ich weiß nicht, wie ich einen Rand auf einer bestimmten Seite, oben oder unten, auf einer beliebigen Seite hinzufügen soll ... layer.border zeichnet den Rand für die gesamte Ansicht ...

120
manonthemoon

Ich betrachte die Unterklasse UIView und überschreibe drawRect overerkill hier. Fügen Sie eine Erweiterung für UIView hinzu und fügen Sie Unteransichten für den Rahmen hinzu.

@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

Mit diesem Code sind Sie auch nicht an Ihre Unterklasse gebunden. Sie können ihn auf alles anwenden, was von UIView übernommen wird - wieder verwendbar in Ihrem Projekt und allen anderen. Übergeben Sie andere Argumente an Ihre Methoden, um andere Farben und Breiten zu definieren. Viele Optionen.

185
Adam Waite

Schnelle Version von Adam Waites fantastischer 5/5/15 Zusatz :

extension CALayer {

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

    var border = CALayer()

    switch Edge {
    case .Top:
        border.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), thickness)
        break
    case .Bottom:
        border.frame = CGRectMake(0, CGRectGetHeight(self.frame) - thickness, CGRectGetWidth(self.frame), thickness)
        break
    case .Left:
        border.frame = CGRectMake(0, 0, thickness, CGRectGetHeight(self.frame))
        break
    case .Right:
        border.frame = CGRectMake(CGRectGetWidth(self.frame) - thickness, 0, thickness, CGRectGetHeight(self.frame))
        break
    default:
        break
    }

    border.backgroundColor = color.CGColor;

    addSublayer(border)
  }
}

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

        border.backgroundColor = color.cgColor;

        addSublayer(border)
    }
}
83
Dan

Der beste Weg für mich ist eine Kategorie in UIView. Sie können jedoch Ansichten anstelle von CALayers hinzufügen, sodass wir AutoresizingMasks nutzen können, um sicherzustellen, dass die Größe der Ränder zusammen mit dem Superview geändert wird.

- (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];
}
40
Pauls

Swift 3.0

Swift 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: self.frame.width, height: thickness)
            break
        case UIRectEdge.bottom:
            border.frame = CGRect(x:0, y:self.frame.height - thickness, width:self.frame.width, height:thickness)
            break
        case UIRectEdge.left:
            border.frame = CGRect(x:0, y:0, width: thickness, height: self.frame.height)
            break
        case UIRectEdge.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)
    }

}
23
AleyRobotics

Unterklasse UIView und implementieren Sie drawRect: in Ihrer Unterklasse, z. B .:

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

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

Dies zeichnet eine rote Linie von 2 Pixeln als oberen Rand. Alle anderen Variationen, die Sie erwähnen, sind für den Leser eine unbedeutende Übung.

Quartz 2D-Programmierhandbuch wird empfohlen.

21
FluffulousChimp

Code für die ausgewählte Antwort, falls dies gewünscht wird.

HINWEIS: Dies funktioniert nicht mit Autolayout (aka, Drehen von Geräten in die Landschaft usw.). 

Definieren Sie zuerst eine Dicke:

NSInteger borderThickness = 1;

Dann kopieren Sie einfach eine oder alle dieser Optionen, um den Rahmen festzulegen, den Sie festlegen möchten.

Oberer Rand

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

Untere Grenze

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

Linke Grenze

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

Rechte Grenze

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];
19
Travis M.

Schnelle Version:

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)

Bearbeiten: Für aktualisierte Versionen überprüfen Sie mein Repo hier: https://github.com/goktugyil/EZSwiftExtensions/blob/master/Sources/UIViewExtensions.Swift

Schauen Sie sich die addBorder-Teile an

13
Esqarrouth

Alte Frage, aber die Autolayout-Lösung mit Anpassungen der Laufzeitgrenze fehlt noch.

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

Die folgende UIView-Erweiterung fügt den Rahmen nur an den angegebenen Kanten hinzu. Wenn Sie die Kanten zur Laufzeit ändern, werden die Ränder entsprechend angepasst.

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

// MARK: - LeftBorder für Ansicht hinzufügen

(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: - RightBorder für Ansicht hinzufügen

(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: - Unterer Rand für Ansicht hinzufügen

(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];
}
4
Priyanka Jadhav

Ich nahm sowohl die Antworten von Adam Waite als auch Pauls und kombinierte sie. Ich habe auch die Möglichkeit hinzugefügt, die ausgewählten Kanten zusammen zu pfeifen, sodass Sie nur eine Funktion wie folgt aufrufen müssen:

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

oder so:

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

Was Sie implementieren müssen, ist eine Kategorie in UIView, wie in anderen Antworten mit der folgenden Implementierung vorgeschlagen:

- (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];
    }
}
4
Maco03

Hier ist eine einfache Lösung. Fügen Sie Ihrer UIView ein Label hinzu, löschen Sie den Text auf dem Label und legen Sie die Hintergrundfarbe des Labels als Randfarbe fest. Legen Sie den Ursprung (x,y) Ihres Labels als den Ursprung (x,y) Ihrer Ansicht fest. und legen Sie die Breite des Etiketts auf die Breite Ihrer UIView fest, und legen Sie die Höhe auf 1 oder 2 fest (für Ihre Randhöhe oben in Ihrer UIView). Und das sollte den Trick tun.

3
If Pollavith

Ich habe einige Änderungen an Dans Antwort vorgenommen, damit ich mit einem Befehl Ränder an mehreren Kanten hinzufügen kann:

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

Hier ist der vollständige Code:

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

Swift 4.2 und AutoLayout

Ich habe die angebotenen Lösungen durchgesehen. Viele basieren auf Frames. Dies ist eine einfache Erweiterung, die mit AutoLayout funktioniert. Verwenden Sie Ansicht anstelle von Ebene, um sicherzustellen, dass AutoLayout - Einzelne Unteransicht mit 4 Einschränkungen verwendet werden kann

Verwenden Sie wie folgt:

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

Meine Antwort auf eine ähnliche Frage: https://stackoverflow.com/a/27141956/435766 .__ Ich persönlich ziehe es vor, auf dieser Kategorie die Kategorie zu durchlaufen, da ich sie auf jeder verwenden möchte Unterklasse von UIView.

2
P. Unto

Aufbauend auf der Antwort von NSBum habe ich einen ähnlichen Ansatz gewählt und diese einfache UIView-Unterklasse erstellt, sodass sie im Interface Builder funktioniert und mit Einschränkungen arbeitet: github link
Durch die Verwendung von CGContextFillRect anstelle von CGContextStrokePath konnte ich die Linien vorhersehbar vollständig in den Grenzen der Ansicht halten.

Hier ist mein Blog-Post darüber: http://natrosoft.com/?p=55

- Legen Sie einfach eine UIView im Interface Builder ab und ändern Sie den Klassentyp in NAUIViewWithBorders.
-- Führen Sie dann in viewDidLoad Ihres VC Folgendes aus: 

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

Hier ist ein direkter Link zur Datei .m , so dass Sie die Implementierung sehen können . Es gibt auch ein Demo-Projekt. Hoffe das hilft jemandem :)

2
n8tr

Posten Sie einfach hier, um jemandem zu helfen, der nach neuen Grenzen sucht. Ich habe ein paar Änderungen in der akzeptierten Antwort hier vorgenommen Swift-Label nur Rahmen links . Geänderte Breite für den Fall UIRectEdge.Top Von CGRectGetHeight(self.frame) zu CGRectGetWidth(self.frame) und für den Fall UIRectEdge.Bottom Von UIScreen.mainScreen().bounds.width zu CGRectGetWidth(self.frame) um Grenzen richtig zu bekommen. Mit Swift 2.

Schließlich ist die Erweiterung:

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

}
1
Kavisha_31

Ich habe eine Lösung mit Swift 4.1 gefunden, die AutoLayout und UIViews verwendet, damit die Größe der Ansicht angepasst wird.

Es basiert auf der Antwort von @AdamWaite, löst jedoch das Problem für Tabellensichtzellen, in denen die Zellen wiederverwendet werden. Wenn der vorherige Rahmen nicht entfernt wird, bevor ein neuer hinzugefügt wird, enthält die wiederverwendete Zelle mehrere Rahmen.

Dies wird gelöst, indem eine Dummy-BorderView-Klasse erstellt und die Unteransichten nach den Rahmen durchsucht und entfernt werden.

Dieser Code verwendet SnapKit für Einschränkungen und CocoaLumberjack für das Debuggen. Wenn Sie diese nicht verwenden, sollte es recht einfach sein

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

Fügen Sie diesen Code hinzu und rufen Sie innerhalb einer Klasse, die UIView auf, folgende Klasse auf:

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

Wenn ich aus dem Storyboard heraus baue, ziehe ich es vor, eine UIView hinter meiner nützlichen UIView... hinzuzufügen. Wenn ich oben auf meiner UIView eine Umrandung erstellen möchte, erhöhe ich nur die Höhe des Hintergrunds UIView um die Umrandungsbreite. Das gleiche kann für jede andere Seite gemacht werden :)

1
Adrián Rivero

Swift 3 Version

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

Um einen entsprechenden Rahmen festzulegen, müssen Sie die viewDidLayoutSubviews () -Methode überschreiben:

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

Hier ist eine Swift 4-Version von Pauls Antwort

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

}
1
Ali Seymen

Inspiriert von @Addison Ich habe die Erweiterung ohne die Verwendung eines Drittanbieter-Frameworks neu geschrieben, da er SnapKit und CocoaLumberjack verwendet hat.

Wie beim @Addisons-Ansatz werden auch zuvor hinzugefügte Rahmen entfernt. Diese Implementierung sollte Nice mit wiederverwendbaren Ansichten als Tabellenzellen und Sammelzellen spielen.

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

Falls jemand jemals eine Xamarin-Version benötigt:

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

Sie können diese Sammlung von UIKit- und Foundation-Kategorien auch überprüfen: https://github.com/leszek-s/LSCategories

Es ermöglicht das Hinzufügen eines Rahmens auf einer Seite von UIView mit einer einzelnen Codezeile:

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

und die Ansichtsdrehung wird ordnungsgemäß verarbeitet, während die meisten hier veröffentlichten Antworten nicht gut funktionieren.

0
Leszek Szary

Konvertiere DanShev Antwort auf 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)
}
}
0
ADS

Ich persönlich mag die Unterklassifizierung von view + drawRect, aber hier geht es nur um eine andere Möglichkeit (und es funktioniert ähnlich wie die akzeptierte Antwort von @If Pollavith):

Ihre neue Rahmenebene kann so eingestellt werden, dass sie alle gewünschten Abmessungen hat. So wie bei @ If Pollaviths Antwort erstellen Sie eine Ebene, die so groß ist, wie Sie möchten, und so breit wie die Ansicht, die Sie umrandet haben möchten. Verwenden Sie die Bilddefinition der Ebene, um sie an der gewünschten Stelle zu platzieren, und fügen Sie sie Ihrer Ansicht dann als Unterebene hinzu.

Als Referenz diente ich selbst dazu, auf der LEFT-HAND-Seite der Ansicht eine Grenze zu setzen (bitte nicht diesen Code ausschneiden und einfügen, sondern nur "mich"), da an der Oberseite der Ansicht keine Grenze gesetzt wird - Das Ändern des Codes ist einfach genug):

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

Ich denke, der einzige moderate Vorteil dabei ist, und wenn man ein kleines UIView oder UILabel macht, ist der CALayer angeblich "leichter", und es gibt (wie in Meinungen) eine Menge interessanter Ansichten über das Überschreiben von drawRect im Vergleich zur Verwendung von CALayers (wie hier) : iOS: Verwenden von UIView 'drawRect:' vs. delagate seiner Ebene 'drawLayer: inContext:' ).

Animal451

Ich mag die Farbe Blau.

0
Animal451

In Swift 4 und 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)
0
Naishta

Für Xamarin in C # erstelle ich beim Hinzufügen der Unterebene den Rand inline

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

Sie können dies (wie von anderen vorgeschlagen) für den unteren, linken und rechten Rand anordnen.

0
Craig Champion

Für mich arbeitet

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

Hinweis: Die meisten Lösungen hier sind nicht anpassungsfähig und können ihre Größe nicht ändern. Die Lösungen, deren Größe sich ändert, wirken sich massiv auf Ihre Startzeit aus, da sie viel CPU beanspruchen.

Sie können diese Lösung darunter verwenden. Es funktioniert mit UIBezierPaths, die leichter als Layer sind und schnelle Startzeiten verursachen. Es ist einfach zu bedienen, siehe Anweisungen unten.

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. Legen Sie für Ihre UIView-Klasse ResizeBorderView fest
  2. Legen Sie Farbe und Linienbreite mit yourview.color und yourview.lineWidth in Ihrer viewDidAppear-Methode fest
  3. Stellen Sie die Kanten ein, zum Beispiel: yourview.edges = [.right, .left] ([.all]) für alle
  4. Genießen Sie einen schnellen Einstieg und die Anpassung der Grenzen
0
J. Doe

Zum Einstellen der oberen und unteren Umrandung für eine UIView in Swift.

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)
0
Sudhi 9135

Zusätzlich zu n8tr kann hinzugefügt werden, dass es möglich ist, sie vom Storyboard aus festzulegen:
- fügen Sie zwei Eigenschaften wie borderColor und borderWidth in der .h-Datei hinzu;
- dann könnten Sie keyPaths direkt im Storyboard hinzufügen, siehe Link zu screenshot

0