Tengo un par de UIButtons, y en IB están configurados en Aspect Fit, pero por alguna razón siempre se estiran. ¿Hay algo más que tengas que configurar? Probé todos los modos de vista diferentes y ninguno de ellos funciona, todos se estiran.
Tengo un par de UIButtons, y en IB están configurados en Aspect Fit, pero por alguna razón siempre se estiran. ¿Hay algo más que tengas que configurar? Probé todos los modos de vista diferentes y ninguno de ellos funciona, todos se estiran.
Respuestas:
Ya tuve ese problema antes. Lo resolví poniendo mi imagen en un lugar UIImageView
donde la contentMode
configuración realmente funciona, y colocando una personalizada transparente UIButton
encima de eso.
EDITAR: Esta respuesta es obsoleta. Consulte la respuesta de @Werner Altewischer para obtener la respuesta correcta en las versiones modernas de iOS.
La solución es establecer contentMode
en la imageView
propiedad de UIButton
. El UIButton
tiene que ser creado con el tipo personalizado para que esto funcione creo (de lo contrario nil
se devuelve para esta propiedad).
[button.imageView setContentMode:UIViewContentModeScaleAspectFit];
button.imageView!.contentMode = UIViewContentMode.scaleAspectFit
Este método me funcionó muy bien:
En Xib seleccione el botón y configure user defined runtime attributes
:
self.imageView.contentMode
Number
1
Usamos number porque no puedes usar enum allí. Pero UIViewContentModeScaleAspectFit es igual a 1.
extension UIButton { @IBInspectable var imageContentMode: Int { get {return imageView?.contentMode.rawValue ?? 0} set {imageView?.contentMode = UIViewContentMode(rawValue: newValue) ?? .scaleAspectFit} } }
imageView.contentMode
funcionó para mí!
Si está haciendo esto en Interface Builder, puede usar el inspector de atributos en tiempo de ejecución para configurarlo directamente sin ningún código.
Establezca la ruta de la clave en el botón para que sea "imageView.contentMode" con un tipo de "Número" y un valor de "1" (o el modo que desee).
Utilice imageView del botón para contentMode. No directamente en el propio botón.
homeButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
homeButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
homeButton.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
[homeButton setImage:[UIImage imageNamed:kPNGLogo] forState:UIControlStateNormal];
Si coloca la imagen UIImageView
detrás del botón, perderá la funcionalidad incorporada de la UIButton
clase, como adjustsImageWhenHighlighted
y adjustsImageWhenDisabled
, y, por supuesto, la capacidad de configurar diferentes imágenes para diferentes estados (sin la molestia de hacerlo usted mismo).
Si queremos tener una imagen sin estirar para todos los estados de control , una cosa es obtener la imagen usando imageWithCGImage:scale:orientation
, como en el siguiente método:
- (UIImage *) getScaledImage:(UIImage *)img insideButton:(UIButton *)btn {
// Check which dimension (width or height) to pay respect to and
// calculate the scale factor
CGFloat imgRatio = img.size.width / img.size.height,
btnRatio = btn.frame.size.width / btn.frame.size.height,
scaleFactor = (imgRatio > btnRatio
? img.size.width / btn.frame.size.width
: img.size.height / btn.frame.size.height;
// Create image using scale factor
UIImage *scaledImg = [UIImage imageWithCGImage:[img CGImage]
scale:scaleFactor
orientation:UIImageOrientationUp];
return scaledImg;
}
Para implementar esto escribiríamos:
UIImage *scaledImg = [self getScaledImage:myBtnImg insideButton:myBtn];
[myBtn setImage:scaledImg forState:UIControlStateNormal];
Esto debería evitar que la imagen se estire en todos los estados de control. Me funcionó, ¡pero avíseme si no funciona!
NOTA: Aquí estamos abordando un problema relacionado con UIButton
, pero insideButton:
bien podría ser insideView:
, o lo que sea que a uno le gustaría encajar la imagen.
Tuve este problema hace un tiempo. El problema que tuve fue que estaba tratando de aplicar este efecto al UIButton de fondo, que es limitado y, por lo tanto, significa que no puede ajustarlo tan fácilmente.
El truco es configurarlo como solo una imagen y luego aplicar la técnica de @ayreguitar y eso debería solucionarlo.
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setContentMode:UIViewContentModeScaleAspectFill];
[myButton setImage:@"myImage.png" forState:UIControlStateNormal];
Esto funcionó para mi
[button.imageView setContentMode:UIViewContentModeScaleAspectFit];
Gracias a @ayreguitar por su comentario
Aquí hay una respuesta alternativa en rápido:
myButton.imageView?.contentMode = .ScaleAspectFit
Combinando algunas respuestas diferentes en una solución: cree un botón con un tipo personalizado, establezca la propiedad imageView contentMode del botón y establezca la imagen para el botón (no la imagen de fondo, que aún se escalará para llenar).
//Objective-C:
UIImage *image = [UIImage imageNamed:"myImageName.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;
//Swift:
let image = UIImage(named: "myImageName.png")
let button = UIButton(type: .custom)
button.imageView?.contentMode = .scaleAspectFit
button.setImage(image, for: .normal)
btn.imageView.contentMode = UIViewContentModeScaleAspectFit;
Esta respuesta se basa en la respuesta de @ WernerAltewischer .
Para evitar tener que conectar mi botón a un IBOutlet para ejecutar el código en él, subclasé la clase de UIButton:
// .h
@interface UIButtonWithImageAspectFit : UIButton
@end
// .m
@implementation UIButtonWithImageAspectFit
- (void) awakeFromNib {
[self.imageView setContentMode:UIViewContentModeScaleAspectFit];
}
@end
Ahora cree un botón personalizado en su xib y configure su imagen (no la imagen de fondo):
Luego, establezca su clase:
¡Listo!
En lugar del
ajuste de aspecto de la imagen de su botón, ahora es el esperado:
ios 12. Debes agregar también la alineación de contenido
class FitButton: UIButton {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
self.imageView?.contentMode = .scaleAspectFill
self.contentHorizontalAlignment = .fill
self.contentVerticalAlignment = .fill
super.layoutSubviews()
}
}
Los modos de contenido de UIView se aplican al "contenido" del CALayer correspondiente. Esto funciona para UIImageView
s porque establecen el CALayer
contenido en el correspondiente CGImage
.
drawRect:
finalmente se renderiza al contenido de la capa.
Un personalizado UIButton
(hasta donde yo sé) no tiene contenido (los botones de estilo rectángulo redondeado pueden renderizarse usando contenido). El botón tiene subvistas: el fondo UIImageView
, la imagen UIImageView
y el título UILabel
. Configurar el contentMode
en las subvistas puede hacer lo que quiera, pero jugar con la UIButton
jerarquía de vistas es un poco prohibido .
Cambiar UIButton.imageView.contentMode
no funcionó para mí.
Resolví el problema configurando la imagen en la propiedad 'Fondo'.
Puede agregar una restricción de relación si lo necesita
Esto se superpone a muchas de las otras respuestas, pero la solución para mí fue
contentMode
del UIImageView
para el botón en .ScaleAspectFit
- lo que se puede hacer en los "Atributos de tiempo de ejecución definidos por el usuario" en Interface Builder (es decir self.imageView.contentMode
, Número, 1) o en unUIButton
subclase;Similar a @Guillaume, he creado una subclase de UIButton como Swift-File. Luego configure mi clase personalizada en el Interface Builder:
Y aquí el archivo Swift:
import UIKit
class TRAspectButton : UIButton {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.imageView?.contentMode = .ScaleAspectFit
}
}
Tuve el mismo problema, pero no pude hacerlo funcionar (tal vez sea un error con el SDK).
Finalmente, como solución, coloqué un UIImageView
detrás de mi botón y configuré las opciones que quería en eso, luego simplemente coloqué un espacio UIButton
en blanco encima.