Domanda

Ho il seguente codice ...

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

... l'idea è che posso avere un testo a più righe per il pulsante, ma il testo è sempre oscurato dallo sfondoImmagine di UIButton. Una chiamata di registrazione per mostrare le visualizzazioni secondarie del pulsante mostra che UILabel è stato aggiunto, ma il testo stesso non può essere visto. È un bug in UIButton o sto facendo qualcosa di sbagliato?

È stato utile?

Soluzione

Per iOS 6 e versioni successive, utilizzare quanto segue per consentire più linee:

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

Per iOS 5 e versioni successive utilizzare quanto segue per consentire più linee:

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

2017, per iOS9 avanti ,

generalmente, fai queste due cose:

  1. scegli " Testo attribuito "
  2. su " Interruzione di linea " popup selezionare " A capo automatico "

Altri suggerimenti

La risposta selezionata è corretta ma se preferisci fare questo genere di cose in Interface Builder puoi farlo:

pic

Se vuoi aggiungere un pulsante con il titolo centrato su più righe, imposta le impostazioni di Interface Builder per il pulsante:

[here]

Per IOS 6:

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

Come

UILineBreakModeWordWrap and UITextAlignmentCenter

sono obsoleti in IOS 6 in poi ..

Per riaffermare il suggerimento di Roger Nolan, ma con un codice esplicito, questa è la soluzione generale:

button.titleLabel?.numberOfLines = 0

SWIFT 3

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

Esiste un modo molto più semplice:

someButton.lineBreakMode = UILineBreakModeWordWrap;

(Modifica per iOS 3 e versioni successive :)

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;

Allineamento a sinistra su iOS7 con autolayout:

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

Prima di tutto, dovresti essere consapevole che UIButton ha già una UILabel al suo interno. Puoi impostarlo usando –setTitle: forState: .

Il problema con il tuo esempio è che devi impostare la proprietà numberOfLines di UILabel su qualcosa di diverso dal suo valore predefinito di 1. Dovresti anche rivedere la proprietà lineBreakMode .

In Xcode 9.3 puoi farlo usando storyboard come sotto,

 inserisci qui la descrizione dell'immagine

Devi impostare il titolo del pulsante text Allineamento al centro

button.titleLabel? .textAlignment = .center

Non è necessario impostare il testo del titolo con una nuova riga (\ n) come di seguito,

button.setTitle (" Buono \ nRisposta ", per: .normale)

Basta impostare il titolo,

button.setTitle (" Good Answer ", per: .normal)

Ecco il risultato,

 inserisci qui la descrizione dell'immagine

Per coloro che stanno utilizzando lo storyboard di Xcode 4, è possibile fare clic sul pulsante e sul pannello Utilità sul lato destro in Impostazioni attributi, vedrai un'opzione per Interruzione di riga. Scegli Word Wrap e dovresti essere a posto.

Le risposte qui ti spiegano come ottenere il titolo del pulsante multilinea a livello di codice.

Volevo solo aggiungere che se si utilizzano gli storyboard, è possibile digitare [Ctrl + Invio] per forzare una nuova riga sul campo del titolo di un pulsante.

HTH

Devi aggiungere questo codice:

buttonLabel.titleLabel.numberOfLines = 0;

Per quanto riguarda l'idea di Brent di mettere il titolo UILabel come una visione tra fratelli, non mi sembra un'ottima idea. Continuo a pensare a problemi di interazione con UILabel a causa dei suoi eventi tattili che non riescono a superare la vista di UIButton.

D'altra parte, con una UILabel come sottoview della UIButton, sono abbastanza a mio agio sapendo che gli eventi touch saranno sempre propagati alla superview della UILabel.

Ho adottato questo approccio e non ho notato nessuno dei problemi segnalati con backgroundImage. Ho aggiunto questo codice nella -titleRectForContentRect: di una sottoclasse UIButton ma il codice può anche essere inserito nella routine di disegno della superview UIButton, che in tal caso sostituirai tutti i riferimenti a sé con la variabile 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;
}

Mi sono preso il tempo e ho scritto qualcosa in più su questo qui . Lì, suggerisco anche una soluzione più breve, anche se non si adatta perfettamente a tutti gli scenari e coinvolge alcune visualizzazioni private. Inoltre, puoi scaricare una sottoclasse UIButton pronta per essere utilizzata.

Se si utilizza il layout automatico su iOS 6, potrebbe essere necessario impostare anche la proprietà favoriteMaxLayoutWidth :

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

Funziona perfettamente.

Aggiungi per usarlo con file di configurazione come Plist, devi usare CDATA per scrivere il titolo multilinea, in questo modo:

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

L'impostazione di lineBreakMode su NSLineBreakByWordWrapping (in IB o codice) rende l'etichetta del pulsante multilinea, ma non influisce sulla cornice del pulsante.

Se il pulsante ha un titolo dinamico, c'è un trucco: mettere UILabel nascosto con lo stesso carattere e legare l'altezza all'altezza del pulsante con il layout; quando si imposta il testo su pulsante ed etichetta e il completamento automatico farà tutto il lavoro.

Nota

L'altezza della dimensione intrinseca del pulsante di una riga è maggiore di quella dell'etichetta, quindi per evitare che l'altezza dell'etichetta si riduca è verticale La priorità di abbraccio al contenuto deve essere maggiore della resistenza alla compressione del contenuto verticale del pulsante.

Se si utilizza il layout automatico.

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

Ho avuto un problema con il layout automatico, dopo aver abilitato la multilinea il risultato è stato questo:
inserisci qui la descrizione dell'immagine
pertanto la dimensione titleLabel non influisce sulla dimensione del pulsante
Ho aggiunto Vincoli in base a contentEdgeInsets (in questo caso contentEdgeInsets era (10, 10, 10, 10)
dopo aver chiamato makeMultiLineSupport () :
inserisci qui la descrizione dell'immagine
spero che ti aiuti (veloce 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)
            ])
    }

}

Al giorno d'oggi, se hai davvero bisogno di questo genere di cose per essere accessibile nel builder di interfacce caso per caso, puoi farlo con una semplice estensione come questa:

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

Quindi puoi semplicemente impostare numberOfLines come attributo su qualsiasi sottoclasse UIButton o UIButton come se fosse un'etichetta. Lo stesso vale per tutta una serie di altri valori solitamente inaccessibili, come il raggio d'angolo del livello di una vista o gli attributi dell'ombra che esso getta.

Rotola la tua classe di pulsanti. È di gran lunga la migliore soluzione a lungo termine. UIButton e le altre classi UIKit sono molto restrittive nel modo in cui è possibile personalizzarle.

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)

Ho incorporato la risposta di jessecurry all'interno di STAButton che fa parte del mio STAControls libreria open source. Attualmente lo uso all'interno di una delle app che sto sviluppando e funziona per le mie esigenze. Sentiti libero di aprire problemi su come migliorarlo o inviarmi richieste pull.

In Swift 5.0 e Xcode 10.2

SharedClass esempio scrivi una volta e usa tutti gli articoli

Questa è la tua classe condivisa (in questo modo usi tutte le proprietà dei componenti)

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

Nella tua ViewController chiama in questo modo

button.btnMultipleLines()//This is your button

Anche se va bene aggiungere una sottoview a un controllo, non c'è alcuna garanzia che funzioni effettivamente, perché il controllo potrebbe non aspettarsi che sia lì e potrebbe quindi comportarsi male. Se riesci a cavartela, aggiungi l'etichetta come una vista fratello del pulsante e imposta la sua cornice in modo che si sovrapponga al pulsante; fintanto che è impostato per apparire in cima al pulsante, nulla che il pulsante possa fare lo oscurerà.

In altre parole:

[button.superview addSubview:myLabel];
myLabel.center = button.center;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top