ios objective-c swift uiimageview rounded-corners

ios - Cómo crear en Swift una imagen de perfil circular o una imagen de esquina redondeada con un borde que no tenga fugas?



objective-c uiimageview (3)

Basándose en el código fuente a continuación:

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

De hecho, puedo renderizar un UIImageView circular o redondeado, pero el problema es que si agregamos el borde, la imagen pierde un poco. Es mucho peor con un UIImageView circular, se escapa cada vez que se dobla el borde, ¡por lo que se ESCANEA EN TODAS PARTES! Puede encontrar una captura de pantalla del resultado a continuación:

¿Alguna forma de arreglar eso en Swift? Cualquier código de muestra que responda a esta pregunta será muy apreciado.

Nota: en la medida de lo posible, la solución debe ser compatible con iOS 7 y 8+.


Si puedo sugerir una solución rápida y sucia:

En lugar de agregar un borde a la vista de la imagen, puede agregar otra vista blanca debajo de la vista de la imagen. Haz que la vista se extienda 10 puntos en cualquier dirección y dale un radio de esquina de 20.0. Dale a la vista de la imagen un radio de esquina de 10.0.


Trabajé para mejorar el código, pero sigue fallando. Trabajaré en ello, pero parece que tengo una versión (aproximada) funcionando:

Editar actualizado con una versión un poco más agradable. No me gusta el método init:coder , pero tal vez eso puede tener en cuenta / mejorar

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

Avísame si ese es el tipo de cosa que estás buscando.

Una pequeña explicación:

Como estoy seguro de que has encontrado, el "borde" que iOS puede aplicar no es perfecto, y muestra las esquinas por alguna razón. Encontré algunas otras soluciones pero ninguna parecía funcionar. La razón por la cual esta es una subclase de UIView , y no UIImageView , es que drawRect: no se llama para las subclases de UIImageView . No estoy seguro del rendimiento de este código, pero parece bueno a partir de mis pruebas (limitadas)

Código original:

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


Primera solución

Basándose en la sugerencia de @Jesper Schläger

"Si puedo sugerir una solución rápida y sucia:

En lugar de agregar un borde a la vista de la imagen, puede agregar otra vista blanca debajo de la vista de la imagen. Haz que la vista se extienda 10 puntos en cualquier dirección y dale un radio de esquina de 20.0. Dale a la vista de la imagen un radio de esquina de 10.0 ".

Encuentre la implementación de Swift a continuación:

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

Segunda solución

Sería establecer una máscara circular sobre un CALayer.

Encuentre la implementación de Objective-C de esta segunda solución a continuación:

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

Si comenta desde la línea UIBezierPath *maskingPath = [UIBezierPath bezierPath]; a través de [maskedLayer setMask:maskingLayer]; Verás que la capa es un cuadrado. Sin embargo, cuando estas líneas no son comentadas, la capa es un círculo.

Nota: No probé esta segunda solución ni proporcioné la implementación de Swift, así que siéntete libre de probarla y decirme si funciona o no a través de la sección de comentarios a continuación. También puede editar esta publicación añadiendo la implementación de Swift de esta segunda solución.