[ios] Come si aggiunge il testo multilinea a un UIButton?



10 Answers

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

Question

Ho il codice seguente...

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 da backgroundImage di UIButton. Una chiamata di registrazione per mostrare le sottoview del pulsante mostra che UILabel è stato aggiunto, ma il testo stesso non può essere visto. Si tratta di un bug in UIButton o sto facendo qualcosa di sbagliato?




L'impostazione di LineBreakMode su NSLineBreakByWordWrapping (in IB o in codice) rende l'etichetta del pulsante su più righe, ma non influisce sul frame del pulsante.

Se il pulsante ha un titolo dinamico, c'è un trucco: mettere UILabel nascosto con lo stesso carattere e legare la sua altezza all'altezza del pulsante con il layout; quando si imposta il testo su pulsante e l'etichetta e l'autolayout eseguiranno 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, la priorità verticale di abbraccio del contenuto deve essere maggiore della resistenza alla compressione del contenuto verticale del pulsante.




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 farla franca, aggiungi l'etichetta come vista di pari livello del pulsante e imposta la sua cornice in modo che si sovrapponga al pulsante; fino a quando è 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;



Allinea a sinistra su iOS7 con autolayout:

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



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

self.btnError.titleLabel?.textAlignment = .center

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



SWIFT 3

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



rapido 4.0

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



Per quanto riguarda l'idea di Brent di mettere il titolo UILabel come fratello, non mi sembra una buona idea. Continuo a pensare a problemi di interazione con UILabel a causa dei suoi eventi di tocco che non passano attraverso la vista di UIButton.

D'altra parte, con un UILabel come sottoview di UIButton, sono abbastanza sicuro sapendo che gli eventi touch saranno sempre propagati alla superview di UILabel.

Ho preso questo approccio e non ho notato nessuno dei problemi segnalati con backgroundImage. Ho aggiunto questo codice nel -titleRectForContentRect: di una sottoclasse UIButton ma il codice può anche essere inserito nella routine di disegno della superview di UIButton, che in questo caso sostituirà tutti i riferimenti a self con la variabile di 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 un po 'di più su questo here . Lì, indico anche una soluzione più breve, anche se non si adatta perfettamente a tutti gli scenari e coinvolge alcune attività di pirateria privata. Inoltre, puoi scaricare una sottoclasse UIButton pronta per essere utilizzata.




Devi aggiungere questo codice:

buttonLabel.titleLabel.numberOfLines = 0;



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

[ ]




Per coloro che utilizzano lo storyboard di Xcode 4, puoi fare clic sul pulsante e sul lato destro del pannello Utilità sotto Impostazioni Inspection, vedrai un'opzione per Line Break. Scegli Word Wrap e dovresti essere pronto.






Related