Pregunta

Tengo el siguiente código ...

UILabel *buttonLabel = [[UILabel alloc] initWithFrame:targetButton.bounds];
buttonLabel.text = @"Long text string";
[targetButton addSubview:buttonLabel];
[targetButton bringSubviewToFront:buttonLabel];

... la idea es que puedo tener texto de varias líneas para el botón, pero el texto siempre está oculto por la imagen de fondo de la UIButton. Una llamada de registro para mostrar las subvistas del botón muestra que se ha agregado UILabel, pero el texto en sí no se puede ver. ¿Es esto un error en UIButton o estoy haciendo algo mal?

¿Fue útil?

Solución

Para iOS 6 y superior, usa lo siguiente para permitir varias líneas:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
// you probably want to center it
button.titleLabel.textAlignment = NSTextAlignmentCenter; // if you want to 
[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];

Para iOS 5 y versiones anteriores, use lo siguiente para permitir varias líneas:

button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
// you probably want to center it
button.titleLabel.textAlignment = UITextAlignmentCenter;
[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];

2017, para iOS9 en adelante ,

en general, solo haz estas dos cosas:

  1. elija " Texto atribuido "
  2. en el " Salto de línea " la ventana emergente selecciona " Envoltura de palabra "

Otros consejos

La respuesta seleccionada es correcta, pero si prefiere hacer este tipo de cosas en Interface Builder, puede hacer esto:

pic

Si desea agregar un botón con el título centrado en varias líneas, establezca la configuración de Interface Builder para el botón:

[here]

Para iOS 6:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;

Como

UILineBreakModeWordWrap and UITextAlignmentCenter

están en desuso en IOS 6 en adelante ...

Para reiterar la sugerencia de Roger Nolan, pero con un código explícito, esta es la solución general:

button.titleLabel?.numberOfLines = 0

SWIFT 3

button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center  
button.setTitle("Button\nTitle",for: .normal)

Hay una manera mucho más fácil:

someButton.lineBreakMode = UILineBreakModeWordWrap;

(Editar para iOS 3 y versiones posteriores :)

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;

Alinear a la izquierda en iOS7 con autolayout:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;

En primer lugar, debe tener en cuenta que UIButton ya tiene una UILabel en su interior. Puede configurarlo usando –setTitle: forState: .

El problema con su ejemplo es que necesita establecer la propiedad numberOfLines de UILabel en un valor distinto de su valor predeterminado de 1. También debe revisar la propiedad lineBreakMode .

En Xcode 9.3 puedes hacerlo usando storyboard como abajo,

 introduce la descripción de la imagen aquí

Necesitas configurar el texto del título del botónAlinear al centro

button.titleLabel? .textAlignment = .center

No es necesario configurar el texto del título con una nueva línea (\ n) como se muestra a continuación,

button.setTitle (" Bien \ nResponder ", para: .normal)

Simplemente establece el título,

button.setTitle (" Buena respuesta ", para: .normal)

Aquí está el resultado,

 introduce la descripción de la imagen aquí

Para aquellos que están usando el guión gráfico de Xcode 4, puede hacer clic en el botón, y en el panel de Utilidades del lado derecho, debajo del Inspector de atributos, verá una opción para Salto de línea. Elige Word Wrap, y deberías estar listo.

Las respuestas aquí le indican cómo lograr el título de un botón multilínea mediante programación.

Solo quería agregar que si está utilizando guiones gráficos, puede escribir [Ctrl + Enter] para forzar una nueva línea en el campo de título de un botón.

HTH

Tienes que agregar este código:

buttonLabel.titleLabel.numberOfLines = 0;

En cuanto a la idea de Brent de poner el título UILabel como una visión de hermanos, no me parece una muy buena idea. Sigo pensando en problemas de interacción con la UILabel debido a que sus eventos táctiles no llegan a la vista de la UIButton.

Por otro lado, con una UILabel como subvista de UIButton, me siento bastante cómodo al saber que los eventos táctiles siempre se propagarán a la vista de supervisión de UILabel.

Tomé este enfoque y no noté ninguno de los problemas reportados con backgroundImage. Agregué este código en el -titleRectForContentRect: de una subclase UIButton, pero el código también se puede colocar en la rutina de dibujo de la supervisión de UIButton, que en ese caso reemplazará todas las referencias a sí mismo con la variable de UIButton.

#define TITLE_LABEL_TAG 1234

- (CGRect)titleRectForContentRect:(CGRect)rect
{   
    // define the desired title inset margins based on the whole rect and its padding
    UIEdgeInsets padding = [self titleEdgeInsets];
    CGRect titleRect = CGRectMake(rect.origin.x    + padding.left, 
                                  rect.origin.x    + padding.top, 
                                  rect.size.width  - (padding.right + padding.left), 
                                  rect.size.height - (padding.bottom + padding].top));

    // save the current title view appearance
    NSString *title = [self currentTitle];
    UIColor  *titleColor = [self currentTitleColor];
    UIColor  *titleShadowColor = [self currentTitleShadowColor];

    // we only want to add our custom label once; only 1st pass shall return nil
    UILabel  *titleLabel = (UILabel*)[self viewWithTag:TITLE_LABEL_TAG];


    if (!titleLabel) 
    {
        // no custom label found (1st pass), we will be creating & adding it as subview
        titleLabel = [[UILabel alloc] initWithFrame:titleRect];
        [titleLabel setTag:TITLE_LABEL_TAG];

        // make it multi-line
        [titleLabel setNumberOfLines:0];
        [titleLabel setLineBreakMode:UILineBreakModeWordWrap];

        // title appearance setup; be at will to modify
        [titleLabel setBackgroundColor:[UIColor clearColor]];
        [titleLabel setFont:[self font]];
        [titleLabel setShadowOffset:CGSizeMake(0, 1)];
        [titleLabel setTextAlignment:UITextAlignmentCenter];

        [self addSubview:titleLabel];
        [titleLabel release];
    }

    // finally, put our label in original title view's state
    [titleLabel setText:title];
    [titleLabel setTextColor:titleColor];
    [titleLabel setShadowColor:titleShadowColor];

    // and return empty rect so that the original title view is hidden
    return CGRectZero;
}

Me tomé el tiempo y escribí un poco más sobre esto here . Ahí, también apunto una solución más corta, aunque no se ajusta a todos los escenarios e involucra algunas vistas privadas de piratería. También allí, puede descargar una subclase UIButton lista para ser utilizada.

Si usa el diseño automático en iOS 6, es posible que también deba configurar la propiedad preferredMaxLayoutWidth :

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
button.titleLabel.preferredMaxLayoutWidth = button.frame.size.width;

Funciona perfectamente.

Agregue para usar esto con un archivo de configuración como Plist, necesita usar CDATA para escribir el título de varias líneas, como este:

<string><![CDATA[Line1
Line2]]></string>

Establecer lineBreakMode en NSLineBreakByWordWrapping (ya sea en IB o en el código) hace que la etiqueta del botón sea multilínea, pero no afecta el marco del botón.

Si el botón tiene un título dinámico, hay un truco: poner UILabel oculto con la misma fuente y vincular su altura a la altura del botón con el diseño; cuando se establece el texto en el botón y la etiqueta y la reproducción automática hará que todo el trabajo funcione.

Nota

La altura del tamaño intrínseco del botón de una línea es más grande que la de la etiqueta, por lo tanto, para evitar que la altura de la etiqueta se contraiga verticalmente, la Prioridad de Abrazar Contenido debe ser mayor que la Resistencia de Compresión del Contenido vertical del botón.

Si usas diseño automático.

button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.numberOfLines = 2

Tuve un problema con el diseño automático, después de habilitar multilínea el resultado fue así:
ingrese la descripción de la imagen aquí
por lo que el tamaño de titleLabel no afecta el tamaño del botón
Agregué Restricciones basado en contentEdgeInsets (en este caso contentEdgeInsets era (10, 10, 10, 10)
después de llamar a makeMultiLineSupport () :
ingrese la descripción de la imagen aquí
Espero que te ayude (Swift 5.0):

extension UIButton {

    func makeMultiLineSupport() {
        guard let titleLabel = titleLabel else {
            return
        }
        titleLabel.numberOfLines = 0
        titleLabel.setContentHuggingPriority(.required, for: .vertical)
        titleLabel.setContentHuggingPriority(.required, for: .horizontal)
        addConstraints([
            .init(item: titleLabel,
                  attribute: .top,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .top,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.top),
            .init(item: titleLabel,
                  attribute: .bottom,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .bottom,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.bottom),
            .init(item: titleLabel,
                  attribute: .left,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .left,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.left),
            .init(item: titleLabel,
                  attribute: .right,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .right,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.right)
            ])
    }

}

En estos días, si realmente necesita que este tipo de cosas sean accesibles en el creador de interfaces caso por caso, puede hacerlo con una extensión simple como esta:

extension UIButton {
    @IBInspectable var numberOfLines: Int {
        get { return titleLabel?.numberOfLines ?? 1 }
        set { titleLabel?.numberOfLines = newValue }
    }
}

Luego, simplemente puede establecer numberOfLines como un atributo en cualquier subclase UIButton o UIButton como si fuera una etiqueta. Lo mismo ocurre con una gran cantidad de otros valores a los que normalmente no se puede acceder, como el radio de la esquina de la capa de una vista o los atributos de la sombra que proyecta.

Tira tu propia clase de botón. Es, con mucho, la mejor solución a largo plazo. UIButton y otras clases de UIKit son muy restrictivas en cuanto a cómo personalizarlas.

self.btnError.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping

self.btnError.titleLabel?.textAlignment = .center

self.btnError.setTitle("Title", for: .normal)

swift 4.0

btn.titleLabel?.lineBreakMode = .byWordWrapping
btn.titleLabel?.textAlignment = .center
btn.setTitle( "Line1\nLine2", for: .normal)

Incorporé respuesta de jessecurry dentro de STAButton que es parte de mi STAControls biblioteca de código abierto. Actualmente lo uso dentro de una de las aplicaciones que estoy desarrollando y funciona para mis necesidades. Siéntase libre de abrir problemas sobre cómo mejorarlo o enviarme solicitudes de extracción.

En Swift 5.0 y Xcode 10.2

El ejemplo de

SharedClass escribe una vez y usa todos los artículos

Esta es su clase compartida (como esta, usa todas las propiedades de los componentes)

import UIKit

class SharedClass: NSObject {

     static let sharedInstance = SharedClass()

     private override init() {

     }
  }

//UIButton extension
extension UIButton {
     //UIButton properties
     func btnMultipleLines() {
         titleLabel?.numberOfLines = 0
         titleLabel?.lineBreakMode = .byWordWrapping
         titleLabel?.textAlignment = .center        
     }
}

En tu ViewController llamada como esta

button.btnMultipleLines()//This is your button

Aunque está bien agregar una subvista a un control, no hay ninguna garantía de que realmente funcione, ya que el control puede esperar que no esté allí y que, por lo tanto, se comporte mal. Si puede salirse con la suya, simplemente agregue la etiqueta como una vista de hermanos del botón y establezca su marco para que se superponga al botón; siempre que esté configurado para aparecer en la parte superior del botón, nada de lo que pueda hacer el botón lo ocultará.

En otras palabras:

[button.superview addSubview:myLabel];
myLabel.center = button.center;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top