Wie fügt man einem UIButton mehrzeiligen Text hinzu?


368

Ich habe den folgenden Code ...

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

... die Idee ist, dass ich mehrzeiligen Text für die Schaltfläche haben kann, aber der Text wird immer durch das Hintergrundbild des UIButton verdeckt. Ein Protokollierungsaufruf zum Anzeigen der Unteransichten der Schaltfläche zeigt an, dass das UILabel hinzugefügt wurde, der Text selbst jedoch nicht angezeigt wird. Ist das ein Fehler in UIButton oder mache ich etwas falsch?


7
button.titleLabel?.numberOfLines = 0
ma11hew28

2
Beachten Sie für diese sehr sehr alte Qualitätssicherung, dass Sie im modernen Xcode SEHR EINFACH "ATTRIBUTED TEXT" wählen und dann trivial "Character Wrap" auswählen.
Fattie

Siehe auch aktualisierte Antwort auf eine ähnliche Frage.
ToolmakerSteve

Siehe diese Antwort (mehrzeilig, Anpassungsbreite, Anpassungshöhe) für Schaltflächentext stackoverflow.com/a/59211399/7523163
Hamid Reza Ansari

Antworten:


676

Verwenden Sie für iOS 6 und höher Folgendes, um mehrere Zeilen zuzulassen:

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

Verwenden Sie für iOS 5 und niedriger Folgendes, um mehrere Zeilen zuzulassen:

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

2017 für iOS9 vorwärts ,

Im Allgemeinen machen Sie einfach diese beiden Dinge:

  1. wählen "Attributed Text".
  2. Wählen Sie im Popup "Zeilenumbruch" die Option "Zeilenumbruch".

5
Bitte beachten Sie, dass diese Zuweisungen in iOS 6 veraltet sind. Die aktualisierte Syntax finden Sie in der Antwort von @NiKKi.
Aaron Brager

6
Nur damit die Leute wissen: Dies funktioniert nicht, wenn Sie NSAttributedString
The Dude

29
Fügen Sie einfach button.titleLabel.numberOfLines = 0 hinzu. Dadurch werden die Zeilen unbegrenzt. Und button.titleLabel.textAlignment = NSTextAlignmentLeft; Wenn Sie linksbündigen Text möchten, da der Titel standardmäßig zentriert ist.
RyJ

4
In button.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
Robert

1
Danke @Robert für die schnelle Lösung. Kann auch Inferenz verwenden und das weglassen NSLineBreakMode, wie folgt : button.titleLabel?.lineBreakMode = .ByWordWrapping.
mjswensen

145

Die ausgewählte Antwort ist korrekt, aber wenn Sie dies in Interface Builder bevorzugen, können Sie Folgendes tun:

Bild


58
Vielen Dank an mein 24-jähriges Ich für das Schreiben dieser Antwort von einem 28-jährigen Ich.
Adam Waite

5
Und bleiben mit dem Interface Builder nur Setup sollte man setzen titleLabel.textAlignmentmit NumberWert 1in User Defined Runtime Attributedden Text zu machen zentriert
AnthoPak

2
Danke an dein 28 Jahre altes Ich von meinem 24 Jahre alten Ich!
Daniel Springer

59

Wenn Sie eine Schaltfläche hinzufügen möchten, deren Titel in mehreren Zeilen zentriert ist, legen Sie die Einstellungen Ihres Interface Builder für die Schaltfläche fest:

[ Hier]


Können Sie eine Textbeschreibung hinzufügen, wie dies erreicht werden kann? Ein Bild ist großartig, aber wenn es nicht mehr verfügbar ist, ist Ihre Antwort nutzlos.
Rory McCrossan

1
@RoryMcCrossan Hallo, ich habe oben ein Bild hinzugefügt. Kannst du es sehen? Bitte beachten Sie, dass Xcode 7 immer noch fehlerhaft ist, sodass der Titel der Schaltfläche möglicherweise verschwindet. Sobald Sie die App ausführen, erhalten Sie jedoch das gewünschte Ergebnis.
user5440039

2
Dies ist eigentlich die beste Antwort in diesem Thread. Funktioniert sofort und zeigt zentrierten Text von IB. Vielen Dank!
RainCast

@ user5440039 Danke für die tolle Antwort. Es ist nicht erforderlich, eine Textbeschreibung hinzuzufügen.
Fattie

54

Für IOS 6:

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

Wie

UILineBreakModeWordWrap and UITextAlignmentCenter

sind ab IOS 6 veraltet.


Im Inneren NSText.hder Foundationgibt es keine veralteten hinzugefügt. Es ist ab 6.0 verfügbar, aber nicht veraltet.
Alex Cio

In button.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping button.titleLabel?.textAlignment = NSTextAlignment.Center
Kürze

30

Um den Vorschlag von Roger Nolan, aber mit explizitem Code, noch einmal zu wiederholen, ist dies die allgemeine Lösung:

button.titleLabel?.numberOfLines = 0

21

SWIFT 3

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

13

In Xcode 9.3 können Sie dies mithilfe des folgenden Storyboards tun :

Geben Sie hier die Bildbeschreibung ein

Sie müssen den Schaltflächentitel textAlignment auf center setzen

button.titleLabel?.textAlignment = .center

Sie müssen den Titeltext nicht mit einer neuen Zeile (\ n) wie unten festlegen.

button.setTitle("Good\nAnswer",for: .normal)

Einfach Titel setzen,

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

Hier ist das Ergebnis,

Geben Sie hier die Bildbeschreibung ein


myButton.titleLabel.textAlignment = NSTextAlignmentCenterAussage ist auch erforderlich.
tounaobun

11

Es gibt einen viel einfacheren Weg:

someButton.lineBreakMode = UILineBreakModeWordWrap;

(Bearbeiten für iOS 3 und höher :)

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;

4
UIButton.lineBreakMode war in 3.0 veraltet, daher ist dies keine gute Option mehr.
Christopher Pickslay

2
lineBreakMode ist nur als direkte Eigenschaft von UIButton veraltet. Wir werden angewiesen, "stattdessen die lineBreakMode-Eigenschaft des titleLabel zu verwenden". Ich habe die Antwort von Valerii entsprechend bearbeitet. Es ist immer noch eine gute Option.
Wienke

11

Links auf iOS7 mit Autolayout ausrichten:

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

9

Ich hatte ein Problem mit dem automatischen Layout. Nach dem Aktivieren der Mehrzeiligkeit sah das Ergebnis folgendermaßen aus: Die Größe hat also keinen Einfluss auf die Größe der Schaltflächen, die ich basierend hinzugefügt habe (in diesem Fall war contentEdgeInsets (10, 10, 10, 10) ) nach dem anruf : hoffe es hilft dir (swift 5.0):
Geben Sie hier die Bildbeschreibung ein
titleLabel
ConstraintscontentEdgeInsets
makeMultiLineSupport()
Geben Sie hier die Bildbeschreibung ein

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

}

Funktioniert perfekt in Swift 5. Ich habe meine Funktion auch hinzugefügt, um Text in der Schaltfläche zu zentrieren. func centerTextInButton () {Wache let titleLabel = titleLabel else {return} titleLabel.textAlignment = .center}
ShadeToD

Vielen Dank. Das ist so eine gute Lösung.
Echelon

Ich fand, dass das Hinzufügen einer Einschränkung nicht erforderlich ist. Setzen Sie den Text einfach, nachdem lineBreakMode / textAlignment / numberOfLines festgelegt wurden. Legen Sie außerdem titleEdgeInsets für den oberen und unteren Einschub fest.
Bill Chan

@ BillChan leider funktioniert das nicht in allen Fällen
Amir Khorsandi

7

Zunächst sollten Sie sich darüber im Klaren sein, dass UIButton bereits ein UILabel enthält. Sie können es mit einstellen –setTitle:forState:.

Das Problem mit Ihrem Beispiel ist, dass Sie die numberOfLinesEigenschaft von UILabel auf einen anderen Wert als den Standardwert 1 setzen müssen. Sie sollten auch die lineBreakModeEigenschaft überprüfen .


Ich kenne die title-Eigenschaft, aber soweit ich das beurteilen kann, ist es unmöglich, sie so einzustellen, dass mehr als eine Zeile verwendet wird, daher dieser Ansatz. Wenn ich das backgroundImage deaktiviere, wird mein UILabel angezeigt, was für mich auf einen Fehler in bringSubviewToFront oder UIButton selbst hindeutet.
Owain Hunt

4

Wenn Sie das Storyboard von Xcode 4 verwenden, können Sie auf die Schaltfläche klicken. Im rechten Bereich Dienstprogramme unter Attributinspektor wird eine Option für Zeilenumbruch angezeigt. Wählen Sie Zeilenumbruch, und Sie sollten bereit sein, loszulegen.


4

In den Antworten erfahren Sie, wie Sie programmgesteuert einen mehrzeiligen Schaltflächentitel erhalten.

Ich wollte nur hinzufügen, dass Sie bei Verwendung von Storyboards [Strg + Eingabetaste] eingeben können, um eine neue Zeile in einem Schaltflächen-Titelfeld zu erzwingen.

HTH


4

Sie müssen diesen Code hinzufügen:

buttonLabel.titleLabel.numberOfLines = 0;

3

Was Brents Idee betrifft, den Titel UILabel als Geschwisteransicht zu verwenden, scheint es mir keine sehr gute Idee zu sein. Ich denke immer wieder an Interaktionsprobleme mit dem UILabel, weil seine Berührungsereignisse nicht durch die Sicht des UIButton gelangen.

Andererseits bin ich mit einem UILabel als Unteransicht des UIButton ziemlich bequem zu wissen, dass die Berührungsereignisse immer an die Übersicht des UILabels weitergegeben werden.

Ich habe diesen Ansatz gewählt und keines der mit backgroundImage gemeldeten Probleme bemerkt. Ich habe diesen Code im -titleRectForContentRect: einer UIButton-Unterklasse hinzugefügt, aber der Code kann auch in die Zeichenroutine der UIButton-Übersicht eingefügt werden. In diesem Fall müssen Sie alle Verweise auf self durch die Variable des UIButton ersetzen.

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

Ich habe die Zeit in Anspruch nehmen und schrieb dies ein bisschen mehr über hier . Dort weise ich auch auf eine kürzere Lösung hin, obwohl sie nicht für alle Szenarien geeignet ist und einige private Ansichten hackt. Dort können Sie auch eine gebrauchsfertige UIButton-Unterklasse herunterladen.


3

Wenn Sie unter iOS 6 das automatische Layout verwenden, müssen Sie möglicherweise auch die folgenden preferredMaxLayoutWidthEigenschaften festlegen :

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

3

Wenn Sie lineBreakMode auf NSLineBreakByWordWrapping (entweder in IB oder Code) setzen, wird die Tastenbezeichnung mehrzeilig, hat jedoch keinen Einfluss auf den Rahmen der Schaltfläche.

Wenn die Schaltfläche einen dynamischen Titel hat, gibt es einen Trick: Setzen Sie ein verstecktes UILabel mit derselben Schriftart und binden Sie die Höhe mit dem Layout an die Höhe der Schaltfläche. Wenn Sie den Text auf Schaltfläche und Beschriftung setzen und das automatische Layout ausführen, wird die gesamte Arbeit erledigt.

Hinweis

Die intrinsische Größenhöhe der einzeiligen Schaltfläche ist größer als die des Etiketts. Um zu verhindern, dass die Höhe des Etiketts schrumpft, muss die vertikale Inhaltsumarmungspriorität größer sein als die vertikale Inhaltskomprimierungsbeständigkeit der Schaltfläche.


3

In Swift 5.0 und Xcode 10.2

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

Rufen Sie in Ihrem ViewController so auf

button.btnMultipleLines()//This is your button

3

Swift 5, Für mehrzeiligen Text in UIButton

  let button = UIButton()
  button.titleLabel?.lineBreakMode = .byWordWrapping
  button.titleLabel?.textAlignment = .center
  button.titleLabel?.numberOfLines = 0 // for Multi line text

2

Es funktioniert perfekt.

Um dies mit einer Konfigurationsdatei wie Plist zu verwenden, müssen Sie CDATA verwenden, um den mehrzeiligen Titel wie folgt zu schreiben:

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

2

Wenn Sie das automatische Layout verwenden.

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

2

schnell 4.0

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

2

Wenn Sie heutzutage wirklich benötigen, dass diese Art von Dingen von Fall zu Fall im Interface Builder verfügbar ist, können Sie dies mit einer einfachen Erweiterung wie der folgenden tun:

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

Dann können Sie einfach numberOfLines als Attribut für eine beliebige UIButton- oder UIButton-Unterklasse festlegen, als wäre es eine Bezeichnung. Gleiches gilt für eine ganze Reihe anderer normalerweise nicht zugänglicher Werte, z. B. den Eckenradius der Ebene einer Ansicht oder die Attribute des Schatten, den sie wirft.


0

Wirf deine eigene Button-Klasse. Es ist bei weitem die beste Lösung auf lange Sicht. UIButton und andere UIKit-Klassen sind sehr restriktiv in der Art und Weise, wie Sie sie anpassen können.


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

self.btnError.titleLabel?.textAlignment = .center

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


0

Um den Abstand der Titelbezeichnung zur Schaltfläche festzulegen, legen Sie titleEdgeInsets und andere Eigenschaften vor setTitle fest:

    let set = UIButton()
    sut.titleLabel?.lineBreakMode = .byWordWrapping
    sut.titleLabel?.numberOfLines = 0
    sut.titleEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 20, right: 20)
    sut.setTitle("Dummy button with long long long long long long long long title", for: .normal)

PS Ich habe getestet, dass die Einstellung titleLabel? .TextAlignment nicht erforderlich ist und der Titel ausgerichtet ist .natural.


-4

Obwohl es in Ordnung ist, einem Steuerelement eine Unteransicht hinzuzufügen, gibt es keine Garantie dafür, dass es tatsächlich funktioniert, da das Steuerelement möglicherweise nicht erwartet, dass es dort vorhanden ist, und sich daher möglicherweise schlecht verhält. Wenn Sie damit durchkommen können, fügen Sie einfach das Etikett als Geschwisteransicht der Schaltfläche hinzu und stellen Sie den Rahmen so ein, dass er die Schaltfläche überlappt. Solange es so eingestellt ist, dass es über der Schaltfläche angezeigt wird, wird es durch nichts, was die Schaltfläche tun kann, verdeckt.

Mit anderen Worten:

[button.superview addSubview:myLabel];
myLabel.center = button.center;

2
Bitte, wenn Sie diese Art von hässlichem Ansatz vorschlagen, machen Sie zumindest keine Fehler in Ihrem Codebeispiel :). Das Etikett sollte nicht die gleiche Mitte wie die Schaltfläche haben, wenn es sich um eine Unteransicht handelt. Verwenden Sie myLabel.frame = button.bounds; oder myLabel.center = cgPointMake (button.frame.size.with * 0.5, button.frame.size.height * 0.5)
JakubKnejzlik

1
@GrizzlyNetch Ich rate ausdrücklich, es nicht als Unteransicht der Schaltfläche hinzuzufügen. addSubview:Hier wird es zur buttonÜbersicht hinzugefügt, wodurch es zu einem Geschwister der Schaltfläche wird, sodass die Übereinstimmung ihrer Zentren korrekt ist.
Brent Royal-Gordon

Ah, mein Fehler! Sie haben Recht, ich habe die "kleine" Tatsache verpasst, dass es in der Übersicht ist: D ... sorry :)
JakubKnejzlik

Da es nicht genau das ist, was gefragt wird, wäre diese Lösung ein schlechter Weg, um die Frage zu implementieren, da die Elementschaltfläche einen Titel hat.
Pablo Blanco

Dies war ein vernünftiger Rat in iPhone OS 2.0. Es gibt jetzt viel bessere Möglichkeiten, dies zu tun. : ^)
Brent Royal-Gordon
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.