2013-03-03 4 views
60

Se un aggiungere un bordo di una vista utilizzando il codice in una vista comeAggiungere un bordo al di fuori di un UIView (invece che all'interno)

self.layer.borderColor = [UIColor yellowColor].CGColor; 
self.layer.borderWidth = 2.0f; 

è aggiunto il confine all'interno della vista come la seguente: enter image description here

la vista di destra è la vista originale, come potete vedere, l'area nera della vista con bordi è inferiore a quella originale. ma quello che voglio ottenere è un bordo esterno alla vista originale, come questo: enter image description here. l'area nera è uguale a quella originale, come posso implementarla?

risposta

83

Purtroppo, non c'è semplicemente una piccola struttura è possibile impostare per allineare il confine verso l'esterno. Disegna allineato verso l'interno perché le operazioni di disegno di default di UIViews disegnano entro i suoi limiti.

La soluzione più semplice che viene in mente sarebbe quello di espandere l'UIView dalla dimensione della larghezza del bordo quando si applica il confine:

CGFloat borderWidth = 2.0f; 

self.frame = CGRectInset(self.frame, -borderWidth, -borderWidth); 
self.layer.borderColor = [UIColor yellowColor].CGColor; 
self.layer.borderWidth = borderWidth; 
+0

ho usato questo in vista del UITableViewCell. ma sulla linea, self.frame = CGRectInset (self.frame, -borderWidth, -borderWidth); La larghezza e l'altezza della vista continua ad aumentare se continuiamo a scorrere la vista tabella. Così ho finito per rimuoverlo. – Neela

+0

Questo metodo continua ad aumentare l'altezza della vista, quindi rimuovo questo codice e utilizzo il seguente codice self.view.layer.borderColor = [[Colore colorWithRed: 209.0f/255.0f verde: 33.0f/255.0f blu: 8.0f/255.0 f alpha: 1.0f] CGColor]; self.view.layer.borderWidth = 1.0f; –

+2

Ho provato questa soluzione in Swift, purtroppo non funziona, il bordo continua a disegnare all'interno di UIImageView – DCDC

1

aumentare la larghezza e l'altezza del telaio di vista con larghezza del bordo prima di aggiungere il confine:

float borderWidth = 2.0f 
CGRect frame = self.frame; 
frame.width += borderWidth; 
frame.height += borderWidth; 
self.layer.borderColor = [UIColor yellowColor].CGColor; 
self.layer.borderWidth = 2.0f; 
12

Beh c'è alcun metodo diretto per farlo Si può considerare un po ' soluzioni alternative.

  1. Change e aumentare il telaio e aggiungere bordercolor come avete fatto
  2. aggiunge una visualizzazione dietro la vista corrente con la dimensione più grande in modo che appaia come border.Can essere lavorato come una classe personalizzata di vista
  3. Se non avete bisogno di un bordo definito (confine netta), allora si può dipendere da ombra al fine

    [view1 setBackgroundColor:[UIColor blackColor]]; 
    UIColor *color = [UIColor yellowColor]; 
    view1.layer.shadowColor = [color CGColor]; 
    view1.layer.shadowRadius = 10.0f; 
    view1.layer.shadowOpacity = 1; 
    view1.layer.shadowOffset = CGSizeZero; 
    view1.layer.masksToBounds = NO; 
    
13

Ok, c'è già è un accettati rispondo ma penso che ci sia un modo migliore per farlo, devi solo avere un nuovo livello un po 'più grande della tua vista e non mascherarlo ai limiti del livello della vista (che in realtà è il comportamento predefinito). Ecco il codice di esempio:

CALayer * externalBorder = [CALayer layer]; 
externalBorder.frame = CGRectMake(-1, -1, myView.frame.size.width+2, myView.frame.size.height+2); 
externalBorder.borderColor = [UIColor blackColor].CGColor; 
externalBorder.borderWidth = 1.0; 

[myView.layer addSublayer:externalBorder]; 
myView.layer.masksToBounds = NO; 

Naturalmente questo è che se si desidera che il confine sia 1 unità di grandi dimensioni, se si vuole più di adattare il borderWidth e la cornice dello strato di conseguenza. Questo è meglio che usare una seconda vista un po 'più grande come un CALayer è più leggero di un UIView e non si dispone non modificare la struttura di myView, che è buono per esempio se myView è un UIImageView

NB: Per me il risultato non era perfetto sul simulatore (il livello non era esattamente nella posizione corretta, quindi lo strato era spesso più spesso su un lato a volte) ma era esattamente ciò che è richiesto sul dispositivo reale.

EDIT

In realtà il problema parlo nel N.B era solo perché avevo ridotto la schermata del simulatore, il formato normale non v'è assolutamente alcun problema

Speranza che aiuta

+0

myView.layer.masksToBounds = NO; sta creando problemi quando myView ha CornerRadius. – umakanta

7

Per un'implementazione Swift, è possibile aggiungere questo come un estensione UIView.

extension UIView { 

    struct Constants { 
     static let ExternalBorderName = "externalBorder" 
    } 

    func addExternalBorder(borderWidth: CGFloat = 2.0, borderColor: UIColor = UIColor.whiteColor()) -> CALayer { 
     let externalBorder = CALayer() 
     externalBorder.frame = CGRectMake(-borderWidth, -borderWidth, frame.size.width + 2 * borderWidth, frame.size.height + 2 * borderWidth) 
     externalBorder.borderColor = borderColor.CGColor 
     externalBorder.borderWidth = borderWidth 
     externalBorder.name = Constants.ExternalBorderName 

     layer.insertSublayer(externalBorder, atIndex: 0) 
     layer.masksToBounds = false 

     return externalBorder 
    } 

    func removeExternalBorders() { 
     layer.sublayers?.filter() { $0.name == Constants.ExternalBorderName }.forEach() { 
      $0.removeFromSuperlayer() 
     } 
    } 

    func removeExternalBorder(externalBorder: CALayer) { 
     guard externalBorder.name == Constants.ExternalBorderName else { return } 
     externalBorder.removeFromSuperlayer() 
    } 

} 
+0

Eccellente! Grazie! Alcune cose sono cambiate in Swift 4 e ora sono diverse, ma Xcode spiega come modificare il codice. E nel metodo 'removeExternalBorder' deve essere 'guard externalBorder.name =='. – DmitryKanunnikoff

2

Con quanto sopra accettati migliore risposta che ho fatto esperienze con tali non belle risultati e bordi sgradevoli:

border without bezier path

Così voglio condividere la mia UIView Swift estensione con voi, che utilizza un UIBezierPath invece come contorno del bordo - senza bordi antiestetici (ispirato a @Fattie):

border with bezier path

// UIView+BezierPathBorder.swift 

import UIKit 

extension UIView { 

    fileprivate var bezierPathIdentifier:String { return "bezierPathBorderLayer" } 

    fileprivate var bezierPathBorder:CAShapeLayer? { 
     return (self.layer.sublayers?.filter({ (layer) -> Bool in 
      return layer.name == self.bezierPathIdentifier && (layer as? CAShapeLayer) != nil 
     }) as? [CAShapeLayer])?.first 
    } 

    func bezierPathBorder(_ color:UIColor = .white, width:CGFloat = 1) { 

     var border = self.bezierPathBorder 
     let path = UIBezierPath(roundedRect: self.bounds, cornerRadius:self.layer.cornerRadius) 
     let mask = CAShapeLayer() 
     mask.path = path.cgPath 
     self.layer.mask = mask 

     if (border == nil) { 
      border = CAShapeLayer() 
      border!.name = self.bezierPathIdentifier 
      self.layer.addSublayer(border!) 
     } 

     border!.frame = self.bounds 
     let pathUsingCorrectInsetIfAny = 
      UIBezierPath(roundedRect: border!.bounds, cornerRadius:self.layer.cornerRadius) 

     border!.path = pathUsingCorrectInsetIfAny.cgPath 
     border!.fillColor = UIColor.clear.cgColor 
     border!.strokeColor = color.cgColor 
     border!.lineWidth = width * 2 
    } 

    func removeBezierPathBorder() { 
     self.layer.mask = nil 
     self.bezierPathBorder?.removeFromSuperlayer() 
    } 

} 

Esempio:

let view = UIView(frame: CGRect(x: 20, y: 20, width: 100, height: 100)) 
view.layer.cornerRadius = view.frame.width/2 
view.backgroundColor = .red 

//add white 2 pixel border outline 
view.bezierPathBorder(.white, width: 2) 

//remove border outline (optional) 
view.removeBezierPathBorder() 
Problemi correlati