Cocoa Touch: Wie ändere ich die Randfarbe und -stärke von UIView?

Antworten:

596

Sie müssen die Ebene der Ansicht verwenden, um die Rahmeneigenschaft festzulegen. z.B:

#import <QuartzCore/QuartzCore.h>
...
view.layer.borderColor = [UIColor redColor].CGColor;
view.layer.borderWidth = 3.0f;

Sie müssen auch eine Verknüpfung mit QuartzCore.framework herstellen, um auf diese Funktionalität zugreifen zu können.

Vladimir
quelle
Gibt es eine Möglichkeit, für jede Seite unterschiedliche Breiten / Farben einzustellen?
lluismontero
2
@lluismontero Ich fürchte, Sie müssen benutzerdefinierte UIView mit drawRect: Methode dafür machen
Vladimir
1
Wenn ich das mache und obendrein eine Animation habe, wie ein modaler UINavigationController, der abweist, sehe ich viele Pannen, es ist schwer zu beschreiben. Wenn ich die Ränder deaktiviere, wird alles wieder normal.
Nicu Surdu
5
Nur ein Kopf hoch für andere. Xcode schlägt vor, UIColor mit CGColorRef as zu verbinden __bridge CGColorRef. Das funktioniert nicht. Es muss [UIColor blackColor].CGColorwie in der Antwort erwähnt sein.
GoodSp33d
6
#import <QuartzCore/QuartzCore.h>wird nicht mehr benötigt.
Bedeutung ist
43

Xcode 6 Update

Seit der neuesten Version von Xcode gibt es eine bessere Lösung dafür:

Mit @IBInspectableIhnen Attribute direkt aus einstellen können innerhalb der Attributes Inspector.

Meine benutzerdefinierte Ansicht @IBInspectable-Attribute

Dies legt das User Defined Runtime Attributesfür Sie fest:

Geben Sie hier die Bildbeschreibung ein

Es gibt zwei Ansätze, um dies einzurichten:

Option 1 (mit Live-Aktualisierung im Storyboard)

  1. Erstellen MyCustomView.
  2. Dies erbt von UIView.
  3. Festlegen @IBDesignable(dadurch wird das View-Update live geschaltet). *
  4. Legen Sie Ihre Laufzeitattribute (Rahmen usw.) mit fest @IBInspectable
  5. Ändern Sie Ihre Views-Klasse in MyCustomView
  6. Bearbeiten Sie im Attributfenster und sehen Sie Änderungen im Storyboard :)

`

@IBDesignable
class MyCustomView: UIView {
    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    @IBInspectable var borderColor: UIColor? {
        didSet {
            layer.borderColor = borderColor?.CGColor
        }
    }
}

* @IBDesignablefunktioniert nur, wenn zu Beginn eingestelltclass MyCustomView

Option 2 (funktioniert seit Swift 1.2 nicht mehr, siehe Kommentare)

Erweitern Sie Ihre UIView-Klasse:

extension UIView {
    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    @IBInspectable var borderColor: UIColor? {
        didSet {
            layer.borderColor = borderColor?.CGColor
        }
    }
}

Auf diese Weise enthält Ihre Standardansicht immer diese zusätzlichen bearbeitbaren Felder Attributes Inspector. Ein weiterer Vorteil ist, dass Sie die Klasse nicht MycustomViewjedes Mal ändern müssen . Ein Nachteil dabei ist jedoch, dass Sie Ihre Änderungen nur sehen, wenn Sie Ihre App ausführen.

MMachinegun
quelle
1
Ihre Erweiterung funktioniert in der neuesten Version von Xcode ab heute nicht mehr.
Edgar Aroutiounian
1
Ich werde @EdgarAroutiounian nur bestätigen, um zu sagen, dass in Swift 1.2 der zweite Ansatz nicht mehr funktioniert
Sergey Grischyov
Was ist mit Objective-C?
Nik Kov
Schauen Sie sich die Antwort von spencery2 weiter unten an. Er hat sich die Zeit genommen, sie in Objective-C zu schreiben:
MMachinegun
Aktualisieren Sie die Erweiterung, um keinen Wert zu speichern, und verwenden Sie set (value) {}, damit {} direkt auf die Ebene zugreift. Dies funktioniert dann.
LightningStryk
17

Sie können auch einen Rahmen mit der Farbe Ihres Wunsches erstellen.

view.layer.borderColor = [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0].CGColor;

* r, g, b sind die Werte zwischen 0 und 255.

Rohan-Patel
quelle
6
Es ist erwähnenswert r, gund bsollte wahrscheinlich Floats sein; Die Teiler sollten auch Schwimmer sein : r / 255.0.
Nein, die C-Syntax entspricht nicht Ihren Angaben. r, g und b können int sein, da C- (und objC IS C-) Promotions int r = 128 auf das Doppelte setzen, wenn: r / 255.0. Übrigens hast du das Doppelte und Clang wird zu CGFloat wechseln.
Ingconti
10

Fügen Sie in der UIView-Erweiterung die folgenden @IBInspectables hinzu

extension UIView {

  @IBInspectable var borderWidth: CGFloat {
    get {
      return layer.borderWidth
    }
    set(newValue) {
      layer.borderWidth = newValue
    }
  }

  @IBInspectable var borderColor: UIColor? {
    get {
      if let color = layer.borderColor {
        return UIColor(CGColor: color)
      }
      return nil
    }
    set(newValue) {
      layer.borderColor = newValue?.CGColor
    }
  }
}

Anschließend sollten Sie in der Lage sein, die Attribute borderColor und borderWidth direkt im Attributinspektor festzulegen. Siehe beigefügtes Bild

Attributinspektor

Bikramjit Singh
quelle
8

Wenn ich die CALayer-Lösung von Vladimir verwende und oben in der Ansicht eine Animation wie ein modaler UINavigationController angezeigt wird, treten viele Störungen auf und es treten Probleme mit der Zeichnungsleistung auf.

Eine andere Möglichkeit, dies zu erreichen, ohne dass es zu Störungen und Leistungseinbußen kommt, besteht darin, eine benutzerdefinierte UIView zu erstellen und die drawRectNachricht folgendermaßen zu implementieren :

- (void)drawRect:(CGRect)rect
{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(contextRef, 1);
    CGContextSetRGBStrokeColor(contextRef, 255.0, 255.0, 255.0, 1.0);
    CGContextStrokeRect(contextRef, rect);    
}
Nicu Surdu
quelle
@Krish Sie speichern die Farbe in einer Variablen. Wenn Sie die Rahmenfarbe ändern müssen, ändern Sie den Variablenwert und rufen setNeedsDisplaydie Ansicht auf. Dadurch wird das Neuzeichnen des UIView erzwungen und implizit erneut aufgerufen drawRect. Nicht getestet, obwohl ...
Nicu Surdu
8
view.layer.borderWidth = 1.0
view.layer.borderColor = UIColor.lightGray.cgColor
Shaiju Mathew
quelle
1
Ich mag es wirklich nicht, wenn Leute ohne Erklärung abgelehnt werden. Es hilft niemandem.
David DelMonte
7

Versuchen Sie diesen Code:

view.layer.borderColor =  [UIColor redColor].CGColor;
view.layer.borderWidth= 2.0;
[view setClipsToBounds:YES];
Vikram Biwal
quelle
4

Ich würde nicht empfehlen, drawRect zu überschreiben, da dies zu einem Leistungseinbruch führt.

Stattdessen würde ich die Eigenschaften der Klasse wie folgt ändern (in Ihrer benutzerdefinierten Ansicht):

  - (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
      self.layer.borderWidth = 2.f;
      self.layer.borderColor = [UIColor redColor].CGColor;
    }
  return self;

Ich habe bei der obigen Vorgehensweise keine Störungen gesehen - ich bin mir nicht sicher, warum das Einfügen des initWithFrame diese stoppt ;-)

DEzra
quelle
3

Ich wollte dies als Kommentar zu @ marczkings Antwort ( Option 1 ) hinzufügen , aber mein niedriger Status bei StackOverflow verhindert dies.

Ich habe eine Portierung von @ marczkings Antwort auf Ziel C gemacht. Funktioniert wie Charme, danke @marczking!

UIView + Border.h:

#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface UIView (Border)

-(void)setBorderColor:(UIColor *)color;
-(void)setBorderWidth:(CGFloat)width;
-(void)setCornerRadius:(CGFloat)radius;

@end

UIView + Border.m:

#import "UIView+Border.h"

@implementation UIView (Border)
// Note: cannot use synthesize in a Category

-(void)setBorderColor:(UIColor *)color
{
    self.layer.borderColor = color.CGColor;
}

-(void)setBorderWidth:(CGFloat)width
{
    self.layer.borderWidth = width;
}

-(void)setCornerRadius:(CGFloat)radius
{
    self.layer.cornerRadius = radius;
    self.layer.masksToBounds = radius > 0;
}

@end
spencery2
quelle
2

@IBInspectable arbeitet für mich unter iOS 9, Swift 2.0

extension UIView {

@IBInspectable var borderWidth: CGFloat {
get {
        return layer.borderWidth
    }
    set(newValue) {
        layer.borderWidth = newValue
    }
}

@IBInspectable var cornerRadius: CGFloat {
    get {
        return layer.cornerRadius
    }
    set(newValue) {
        layer.cornerRadius = newValue
    }
}

@IBInspectable var borderColor: UIColor? {
    get {
        if let color = layer.borderColor {
            return UIColor(CGColor: color)
        }
        return nil
    }
    set(newValue) {
        layer.borderColor = newValue?.CGColor
    }
}
anhtran
quelle
1

Wenn Sie die Ebene einer UIView nicht bearbeiten möchten, können Sie die Ansicht jederzeit in eine andere Ansicht einbetten. In der übergeordneten Ansicht wird die Hintergrundfarbe auf die Rahmenfarbe festgelegt. Es wäre auch etwas größer, je nachdem, wie breit der Rand sein soll.

Dies funktioniert natürlich nur, wenn Ihre Ansicht nicht transparent ist und Sie nur eine einzige Rahmenfarbe wünschen. Das OP wollte die Grenze in der Ansicht selbst, aber dies könnte eine praktikable Alternative sein.

Matt Becker
quelle
0

Wenn Sie auf verschiedenen Seiten unterschiedliche Rahmen hinzufügen möchten, ist es möglicherweise einfach, eine Unteransicht mit dem spezifischen Stil hinzuzufügen.

Yuanfei Zhu
quelle
0

Randfarbe des Elements in Swift 4.2:

let cell = tableView.dequeueReusableCell(withIdentifier: "Cell_lastOrderId") as! Cell_lastOrder
cell.layer.borderWidth = 1
cell.layer.borderColor = UIColor.white.cgColor
cell.layer.cornerRadius = 10
Akhrua
quelle