ios - the - xcode kits
¿Cómo mantener una ronda round imageView usando el diseño automático? (10)
¿Cómo convierto una vista de imagen rectangular en una vista de imagen circular que puede mantener la forma en el diseño automático sin establecer restricciones de ancho y alto? De este modo, permite que imageView defina su tamaño y su tamaño sea más grande y más pequeño en relación con los objetos que lo rodean con restricciones iniciales, finales, superiores e inferiores.
Hice una pregunta similar el otro día, pero creo que esto podría plantearse de una manera más concisa. ¡Muchas gracias!
EDITAR
Ok, comencé a hacer esto lo más simple posible. Tengo una vista llamada "Célula" y un UIImageView llamado "perro" dentro de la celda, y eso es todo. Ya no tengo "incapaz de satisfacer restricciones simultáneamente" en la consola, solo dos vistas simples usando el diseño automático. Todavía estoy tratando de usar este código para redondear el UIImageView:
profileImageView.layer.cornerRadius = profileImageView.frame.size.width / 2
profileImageView.clipsToBounds = true
Aquí está la configuración de restricción de celda:
Aquí está la configuración de restricción de pic de perfil:
Aquí está el resultado sin el código, sin redondeo, pero bonito y cuadrado:
Aquí está el resultado con el código para redondear:
Esto no tiene sentido para mí, porque sin el código de redondeo la imagen es cuadrada, y con el código tiene forma de diamante. Si es cuadrado, ¿no debería ser un círculo sin problemas?
EDIT 2
Esto es lo que sucede cuando elimino la restricción inferior y agrego un multiplicador de .637 para la misma altura a la supervista.
Agregue una restricción de relación de aspecto 1: 1 a la imageView
de imageView
para que permanezca circular, a pesar de los cambios de altura o ancho.
Al agregar una vista como subvista de otra, parece que la vista en red no necesariamente tendrá la misma altura que su supervista. Eso es lo que parece el problema. La solución es no agregar su imageView como una subvista, pero tenerla en la parte superior de su backgroundView. En la imagen de abajo estoy usando un UILabel como mi backgroundView.
También en tu caso, cuando estás configurando la esquina, usa este let radius: CGFloat = self.bounds.size.height / 2.0
.
Con mi solución hacky obtendrá animación de radio de esquina suave junto con el cambio de tamaño de fotograma.
Digamos que tienes ViewSubclass: UIView. Debe contener el siguiente código:
class ViewSubclass: UIView {
var animationDuration : TimeInterval?
let imageView = UIImageView()
//some imageView setup code
override func layoutSubviews() {
super.layoutSubviews()
if let duration = animationDuration {
let anim = CABasicAnimation(keyPath: "cornerRadius")
anim.fromValue = self.imageView.cornerRadius
let radius = self.imageView.frame.size.width / 2
anim.toValue = radius
anim.duration = duration
self.imageView.layer.cornerRadius = radius
self.imageView.layer.add(anim, forKey: "cornerRadius")
} else {
imageView.cornerRadius = imageView.frame.size.width / 2
}
animationDuration = nil
}
}
Entonces, tendrás que hacer esto:
let duration = 0.4 //For example
instanceOfViewSubclass.animationDuration = duration
UIView.animate(withDuration: duration, animations: {
//Your animation
instanceOfViewSubclass.layoutIfNeeded()
})
No es hermoso, y podría no funcionar para multi-animaciones complejas, pero responde la pregunta.
Desafortunadamente no puedes hacer esto usando cornerRadius
y autolayout - CGLayer
no se ve afectado por el autodiseño, por lo que cualquier cambio en el tamaño de la vista no cambiará el radio que se ha establecido una vez, lo que hace que el círculo pierda su forma .
Puede crear una subclase personalizada de UIImageView
y anular las layoutSubviews
de layoutSubviews
para establecer el cornerRadius
cada vez que cornerRadius
los límites de la vista de imagen.
EDITAR
Un ejemplo podría verse más o menos así:
class Foo: UIImageView {
override func layoutSubviews() {
super.layoutSubviews()
let radius: CGFloat = self.bounds.size.width / 2.0
self.layer.cornerRadius = radius
}
}
Y, obviamente, tendrías que restringir el ancho de la instancia de Foobar
para que sea igual a la altura (para mantener un círculo). Probablemente también desee establecer el modo de contentMode
la instancia de Foobar
en UIViewContentMode.ScaleAspectFill
para que sepa cómo dibujar la imagen (esto significa que es probable que la imagen se recorta).
Establecer el radio en viewWillLayoutSubviews resolverá el problema
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
profileImageView.layer.cornerRadius = profileImageView.frame.height / 2.0
}
Se puede hacer fácilmente creando una IBOutlet
para la restricción que debe modificarse en el tiempo de ejecución. A continuación está el código:
Cree un
IBOutlet
para la restricción que debe modificarse en tiempo de ejecución.@IBOutlet var widthConstraint: NSLayoutConstraint!
Agregue el código siguiente en
viewDidLoad()
:self.widthConstraint.constant = imageWidthConstraintConstant()
Debajo de la función determina para los tipos de dispositivo cambiar la restricción de ancho en consecuencia.
func imageWidthConstraintConstant() -> CGFloat {
switch(self.screenWidth()) {
case 375:
return 100
case 414:
return 120
case 320:
return 77
default:
return 77
}
}
Si ha subclasificado el UIImageView. Entonces solo agrega esta pieza de código mágico.
Escrito en: Swift 3
override func layoutSubviews() {
super.layoutSubviews()
if self.isCircular! {
self.layer.cornerRadius = self.bounds.size.width * 0.50
}
}
Tengo el mismo problema, y ahora entiendo lo que sucedió aquí, espero que algunas ideas te ayuden: hay algo diferente entre los remolques:
- su perfilImageView en guión gráfico
- su perfilImageViewView en
viewDidLoad
el tamaño de bound y frame es diferente cuando viewDidLoad
y en el guión gráfico, simplemente porque la vista viewDidLoad
tamaño para diferentes tamaños de dispositivo. Puedes probarlo print(profileImageView.bounds.size)
en viewDidLoad
y viewDidAppear
encontrarás el tamaño en viewDidLoad que estableces. cornerRadius
no es el tamaño real de "ejecución".
un consejo para usted: puede usar una subclase de ImageView para evitarlo, o no lo use en el guión gráfico,
crea una nueva interfaz en tu archivo .h como
@interface CornerClip : UIImageView
@end
y la implementación en el archivo .m como
@implementation cornerClip
-(void)layoutSubviews
{
[super layoutSubviews];
CGFloat radius = self.bounds.size.width / 2.0;
self.layer.cornerRadius = radius;
}
@end
ahora solo da clase como "CornerClip" a tu imagen. 100% trabajando ... Disfruta
Swift 4+ solución limpia basada en la respuesta de omaralbeik
import UIKit
extension UIImageView {
func setRounded(borderWidth: CGFloat = 0.0, borderColor: UIColor = UIColor.clear) {
layer.cornerRadius = frame.width / 2
layer.masksToBounds = true
layer.borderWidth = borderWidth
layer.borderColor = borderColor.cgColor
}
}
Uso de muestra en UIViewController
1. UIImageView simplemente redondeado
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
imageView.setRounded()
}
2.Rounded UIImageView con ancho y color de borde
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
imageView.setRounded(borderWidth: 1.0, borderColor: UIColor.red)
}