2015-03-23 22 views
7

Basandosi sul source code seguito:Come creare in Swift un'immagine di profilo circolare o immagine di angolo arrotondato con un bordo che non perde?

@IBOutlet var myUIImageView: UIImageView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.makingRoundedImageProfileWithRoundedBorder() 
    } 

    private func makingRoundedImageProfileWithRoundedBorder() {  
     // Making a circular image profile. 
//  self.myUIImageView.layer.cornerRadius = self.myUIImageView.frame.size.width/2 
     // Making a rounded image profile. 
     self.myUIImageView.layer.cornerRadius = 20.0 

     self.myUIImageView.clipsToBounds = true 

     // Adding a border to the image profile 
     self.myUIImageView.layer.borderWidth = 10.0 
     self.myUIImageView.layer.borderColor = UIColor.whiteColor().CGColor 
    } 

infatti sono in grado di rendere un UIImageView circolare o arrotondato, ma il problema è che se si aggiunge il confine, l'immagine perde un po '. È peggio di un UIImageView circolare, perde ogni volta che il bordo è piegato, quindi FUGA OVUNQUE! È possibile trovare uno screenshot del risultato qui sotto:

UIImageView rendered

Un modo per rimediare a Swift? Qualsiasi codice di esempio che risponda a questa domanda sarà molto apprezzato.

Nota: per quanto possibile, la soluzione deve essere compatibile con iOS 7 e 8+.

risposta

5

prima soluzione

Basandosi su suggerimento @Jesper Schläger

"Se posso suggerire una soluzione rapida e sporca:

Invece di aggiungere un bordo alla vista delle immagini, è sufficiente aggiungere un'altra vista bianca sotto la vista dell'immagine: aumentare la vista di 10 punti in entrambe le direzioni e assegnargli un raggio d'angolo di 20.0."

Si prega di trovare il Swift implementazione di seguito:

import UIKit 

class ViewController: UIViewController { 

    @IBOutlet var myUIImageView: UIImageView! 

    @IBOutlet var myUIViewBackground: UIView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // Making a circular UIView: cornerRadius = self.myUIImageView.frame.size.width/2 
     // Making a rounded UIView: cornerRadius = 10.0 
     self.roundingUIView(self.myUIImageView, cornerRadiusParam: 10) 
     self.roundingUIView(self.myUIViewBackground, cornerRadiusParam: 20) 
    } 

    private func roundingUIView(let aView: UIView!, let cornerRadiusParam: CGFloat!) { 
     aView.clipsToBounds = true 
     aView.layer.cornerRadius = cornerRadiusParam 
    } 

} 

seconda soluzione

Sarebbe per impostare una maschera cerchio sopra un CALayer

Si prega di trovare il . Objective-C implementazione di questa seconda soluzione di seguito:

CALayer *maskedLayer = [CALayer layer]; 
[maskedLayer setFrame:CGRectMake(50, 50, 100, 100)]; 
[maskedLayer setBackgroundColor:[UIColor blackColor].CGColor]; 

UIBezierPath *maskingPath = [UIBezierPath bezierPath]; 
[maskingPath addArcWithCenter:maskedLayer.position 
         radius:40 
        startAngle:0 
        endAngle:360 
        clockwise:TRUE]; 

CAShapeLayer *maskingLayer = [CAShapeLayer layer]; 
[maskingLayer setPath:maskingPath.CGPath]; 

[maskedLayer setMask:maskingLayer]; 
[self.view.layer addSublayer:maskedLayer]; 

Se si commento fuori dalla linea UIBezierPath *maskingPath = [UIBezierPath bezierPath]; attraverso [maskedLayer setMask:maskingLayer]; si vedrà che il livello è un quadrato. Tuttavia, quando queste righe non sono commentate, il livello è un cerchio.

Nota: non ho testato questa seconda soluzione né fornito l'implementazione Swift, quindi sentitevi liberi di testarlo e fatemi sapere se funziona o meno tramite la sezione commenti qui sotto. Sentiti libero di modificare questo post aggiungendo l'implementazione Swift di questa seconda soluzione.

+0

Nota: un percorso di mascheramento è funzionale ma presenta bordi alias croccanti che non sono ancora stato in grado di correggere http://stackoverflow.com/questions/37092333/path-based-mask-with-nice-anti-aliasing – SimplGy

0

Ho lavorato per migliorare il codice ma continua a bloccarsi. Ci lavorerò sopra, ma mi sembra di avere una versione (approssimativa) funzionante:

Modifica Aggiornato con una versione leggermente migliore. Non mi piace il metodo init:coder ma forse posso fattorizzato/migliorata

class RoundedImageView: UIView { 
    var image: UIImage? { 
     didSet { 
      if let image = image { 
       self.frame = CGRect(x: 0, y: 0, width: image.size.width/image.scale, height: image.size.width/image.scale) 
      } 
     } 
    } 
    var cornerRadius: CGFloat? 

    private class func frameForImage(image: UIImage) -> CGRect { 
     return CGRect(x: 0, y: 0, width: image.size.width/image.scale, height: image.size.width/image.scale) 
    } 

    override func drawRect(rect: CGRect) { 
     if let image = self.image { 
      image.drawInRect(rect) 

      let cornerRadius = self.cornerRadius ?? rect.size.width/10 
      let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius) 
      UIColor.whiteColor().setStroke() 
      path.lineWidth = cornerRadius 
      path.stroke() 
     } 
    } 
} 

let image = UIImage(named: "big-teddy-bear.jpg") 

let imageView = RoundedImageView() 
imageView.image = image 

Fatemi sapere se questo è il genere di cosa che stai cercando.

Una piccola spiegazione:

Come sono sicuro che hai trovato, il "confine" che iOS può applicare non è perfetto, e mostra gli angoli per qualche ragione. Ho trovato alcune altre soluzioni, ma nessuna sembrava funzionare. Il motivo per cui questa è una sottoclasse di UIView e non UIImageView, è quella drawRect: is not called for subclasses of UIImageView. Non sono sicuro circa le prestazioni di questo codice, ma sembra buono dal mio test (limitata)

Codice originale:

class RoundedImageView: UIView { 

    var image: UIImage? { 
     didSet { 
      if let image = image { 
       self.frame = CGRect(x: 0, y: 0, width: image.size.width/image.scale, height: image.size.width/image.scale) 
      } 
     } 
    } 

    private class func frameForImage(image: UIImage) -> CGRect { 
     return CGRect(x: 0, y: 0, width: image.size.width/image.scale, height: image.size.width/image.scale) 
    } 

    override func drawRect(rect: CGRect) { 
     if let image = self.image { 
      self.image?.drawInRect(rect) 

      let path = UIBezierPath(roundedRect: rect, cornerRadius: 50) 
      UIColor.whiteColor().setStroke() 
      path.lineWidth = 10 
      path.stroke() 
     } 
    } 
} 

let image = UIImage(named: "big-teddy-bear.jpg") 

let imageView = RoundedImageView() 
imageView.image = image 
imageView.layer.cornerRadius = 50 
imageView.clipsToBounds = true 
+0

Codice in arresto + Vorrei continuare a utilizzare UIImageView nello storyboard e non utilizzare un UIView se possibile. Quindi sfortunatamente non si adatta alle mie esigenze. –

+0

Non sono sicuro che sia possibile con 'UIImageView', ma mi piacerebbe vedere una soluzione se ne hai una. Puoi pubblicare ulteriori informazioni sull'incidente? Potresti essere in grado di usare 'IBDesignable' per farlo funzionare nel generatore di interfacce, ma non ne sono sicuro. Hai fatto downvote per qualche motivo? –

+0

self.image.drawInRect (rect) // errore fatale: inaspettatamente trovato nil mentre scartando un valore Opzionale –

0

Se mi può suggerire una soluzione rapida e sporca:

Invece di aggiungere un bordo alla vista dell'immagine, è sufficiente aggiungere un'altra vista bianca sotto la vista dell'immagine. Aumentare la vista di 10 punti in entrambe le direzioni e assegnargli un raggio d'angolo di 20.0. Dai alla vista dell'immagine un raggio d'angolo di 10.0.

+0

Grazie Jesper Schläger, la soluzione che risolve il problema e richiede meno codice rispetto all'aggiunta manuale di un bordo a un UIView. Tuttavia in teoria potremmo anche risolvere questo problema, aggiungendo un UIImage a un UIView e disegnando manualmente un bordo attorno alla UIImage, penso che questo sia ciò che @Joseph Duffy cerca di implementare nella sua risposta qui sotto. –

Problemi correlati