Swift - UIButton mit zwei Textzeilen

93

Ich habe mich gefragt, ob es möglich ist, einen UIButton mit zwei Textzeilen zu erstellen. Ich brauche jede Zeile, um eine andere Schriftgröße zu haben. Die erste Linie wird 17 Punkte und die zweite 11 Punkte sein. Ich habe versucht, zwei Beschriftungen in einen UIButton einzufügen, aber ich kann sie nicht dazu bringen, innerhalb der Grenzen der Schaltfläche zu bleiben.

Ich versuche dies alles im UI-Builder zu tun und nicht programmgesteuert.

Vielen Dank

Scott
quelle

Antworten:

245

Es gibt zwei Fragen.

Ich habe mich gefragt, ob es möglich ist, einen UIButton mit zwei Textzeilen zu erstellen

Dies ist über das Storyboard oder programmgesteuert möglich.

Storyboard:

Ändern Sie den ‚Zeilenumbruch - Modus‘ zu Zeichen Wickeln oder Zeilenumbruch und verwenden Alt / Option + Enter - Taste eine neue Zeile in der UIButton des Titelfeld einzugeben.

Geben Sie hier die Bildbeschreibung ein

Programmatisch:

override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        btnTwoLine?.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping;
}

Ich brauche jede Zeile, um eine andere Schriftgröße 1 zu haben

Im schlimmsten Fall können Sie eine benutzerdefinierte UIButtonKlasse verwenden und zwei Beschriftungen hinzufügen.

Der bessere Weg ist, nutzen NSMutableAttributedString. Beachten Sie, dass dies nur programmgesteuert erreicht werden kann.

Swift 5:

@IBOutlet weak var btnTwoLine: UIButton?

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    //applying the line break mode
    textResponseButton?.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping;
    let buttonText: NSString = "hello\nthere"

    //getting the range to separate the button title strings
    let newlineRange: NSRange = buttonText.range(of: "\n")

    //getting both substrings
    var substring1 = ""
    var substring2 = ""

    if(newlineRange.location != NSNotFound) {
        substring1 = buttonText.substring(to: newlineRange.location)
        substring2 = buttonText.substring(from: newlineRange.location)
    }

    //assigning diffrent fonts to both substrings
    let font1: UIFont = UIFont(name: "Arial", size: 17.0)!
    let attributes1 = [NSMutableAttributedString.Key.font: font1]
    let attrString1 = NSMutableAttributedString(string: substring1, attributes: attributes1)

    let font2: UIFont = UIFont(name: "Arial", size: 11.0)!
    let attributes2 = [NSMutableAttributedString.Key.font: font2]
    let attrString2 = NSMutableAttributedString(string: substring2, attributes: attributes2)

    //appending both attributed strings
    attrString1.append(attrString2)

    //assigning the resultant attributed strings to the button
    textResponseButton?.setAttributedTitle(attrString1, for: [])
}

Älterer Swift

@IBOutlet weak var btnTwoLine: UIButton?

override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        //applying the line break mode
        btnTwoLine?.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping;

        var buttonText: NSString = "hello\nthere"

        //getting the range to separate the button title strings
        var newlineRange: NSRange = buttonText.rangeOfString("\n")

        //getting both substrings
        var substring1: NSString = ""
        var substring2: NSString = ""

        if(newlineRange.location != NSNotFound) {
            substring1 = buttonText.substringToIndex(newlineRange.location)
            substring2 = buttonText.substringFromIndex(newlineRange.location)
        }

        //assigning diffrent fonts to both substrings
        let font:UIFont? = UIFont(name: "Arial", size: 17.0)
        let attrString = NSMutableAttributedString(
            string: substring1 as String,
            attributes: NSDictionary(
                object: font!,
                forKey: NSFontAttributeName) as [NSObject : AnyObject])

        let font1:UIFont? = UIFont(name: "Arial", size: 11.0)
        let attrString1 = NSMutableAttributedString(
            string: substring2 as String,
            attributes: NSDictionary(
                object: font1!,
                forKey: NSFontAttributeName) as [NSObject : AnyObject])

        //appending both attributed strings
        attrString.appendAttributedString(attrString1)

        //assigning the resultant attributed strings to the button
        btnTwoLine?.setAttributedTitle(attrString, forState: UIControlState.Normal)

    }

Ausgabe

Geben Sie hier die Bildbeschreibung ein

Shamsudheen TK
quelle
2
Funktioniert super. Ich frage mich jetzt, ob es eine Möglichkeit gibt, den Text in jeder Zeile zu zentrieren, und ob es eine Möglichkeit gibt, mehr Platz zwischen den beiden Zeilen einzufügen.
Scott
3
Sie können beide Zeilentexte an der Mitte ausrichten. Schreiben Sie den folgenden Code: btnTwoLine? .titleLabel? .textAlignment = NSTextAlignment.Center oder verwenden Sie die Storyboard-Datei (Steuerabschnitt-> Ausrichtung)
Shamsudheen TK
Darf ich wissen, was der Zweck ist, mehr Zeilen dazwischen zu setzen?
Shamsudheen TK
Dies hängt von der Größe der Schaltfläche ab. Wenn die Schaltfläche groß ist, befinden sich die beiden Textzeilen genau in der Mitte, mit viel Platz oben und unten. Das ist nicht der Look, den ich wollte.
Scott
Sie müssen hier einige Tricks anwenden :) Sie können mehr Zeilen dazwischen setzen, indem Sie mehrere \ n verwenden. Ich meine, "Hallo \ n \ n \ nthere" gibt Ihnen drei Leerzeichen. Vergessen Sie jedoch nicht, Ihren Code zu ändern var newlineRange: NSRange = buttonText.rangeOfString ("\ n \ n \ n")
Shamsudheen TK
22

Ich habe nach fast demselben Thema gesucht, außer dass ich keine zwei verschiedenen Schriftgrößen benötige. Für den Fall, dass jemand nach einer einfachen Lösung sucht:

    let button = UIButton()
    button.titleLabel?.numberOfLines = 0
    button.titleLabel?.lineBreakMode = .byWordWrapping
    button.setTitle("Foo\nBar", for: .normal)
    button.titleLabel?.textAlignment = .center
    button.sizeToFit()
    button.addTarget(self, action: #selector(rightBarButtonTapped), for: .allEvents)
    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
Nico S.
quelle
12

Ich habe bei den meisten Lösungen ein Problem festgestellt, bei dem beim Umschalten des Zeilenumbruchmodus auf "Zeichenumbruch" die zweite Zeile an der ersten Zeile ausgerichtet bleibt

Alle Linien zentrieren. Ändern Sie einfach den Titel von "Einfach" in "Attributiert" und Sie können jede Linie zentrieren

zentrierter Titel zugeschrieben

Musa almatri
quelle
6

SWIFT 3-Syntax

let str = NSMutableAttributedString(string: "First line\nSecond Line")
str.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: 17), range: NSMakeRange(0, 10))
str.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: 12), range: NSMakeRange(11, 11))
button.setAttributedTitle(str, for: .normal)
Maksim Kniazev
quelle
2
Ich weiß nicht warum, aber ich musste button.titleLabel hinzufügen? .numberOfLines = 0
budidino
Hat in Swift 4 zuerst nicht funktioniert. Sie müssen "Zeilenumbruch" auf "Zeilenumbruch" setzen. Danke Mann :)
Karan Alangat
Die ursprüngliche frühere Antwort ist unten: stackoverflow.com/a/30679547/5318223
Kiril S.
5

Ändern Sie den Zeilenumbruch in Zeichenumbruch, wählen Sie Ihre Schaltfläche aus und wechseln Sie im Attributinspektor zum Zeilenumbruch und ändern Sie ihn in Zeichenumbruch

Geben Sie hier die Bildbeschreibung ein

Sabhay Sardana
quelle
5

Ich habe dies behoben und meine Lösung war nur im Storyboard.

Änderungen:

Es wurde im Identitätsinspektor -> Benutzerdefinierte Laufzeitattribute (diese Schlüsselpfade) hinzugefügt:

  • numberOfLines = 2
  • titleLabel.textAlignment = 1

Benutzerdefinierte Laufzeitattribute

Ich habe dies im Attributinspektor hinzugefügt:

  • Zeilenumbruch = Zeilenumbruch

Zeilenumbruch

A. Trejo
quelle
2

Sie müssen einige davon im Code ausführen. Sie können in IB nicht zwei verschiedene Schriftarten festlegen. Zusätzlich zum Ändern des Zeilenumbruchmodus in Zeichenumbruch benötigen Sie Folgendes, um den Titel festzulegen.

override func viewDidLoad() {
        super.viewDidLoad()
        var str = NSMutableAttributedString(string: "First line\nSecond Line")
        str.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(17), range: NSMakeRange(0, 10))
        str.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(12), range: NSMakeRange(11, 11))
        button.setAttributedTitle(str, forState: .Normal)

    }
rdelmar
quelle
1

Eine Möglichkeit, dies zu tun, sind wohl Etiketten. Ich habe das getan und es scheint in Ordnung zu funktionieren. Ich könnte dies als UIButton erstellen und dann die Beschriftungen verfügbar machen, denke ich. Ich weiß nicht, ob das Sinn macht.

    let firstLabel = UILabel()

    firstLabel.backgroundColor = UIColor.lightGrayColor()
    firstLabel.text = "Hi"
    firstLabel.textColor = UIColor.blueColor()
    firstLabel.textAlignment = NSTextAlignment.Center
    firstLabel.frame = CGRectMake(0, testButton.frame.height * 0.25, testButton.frame.width, testButton.frame.height * 0.2)
    testButton.addSubview(firstLabel)

    let secondLabel = UILabel()

    secondLabel.backgroundColor = UIColor.lightGrayColor()
    secondLabel.textColor = UIColor.blueColor()
    secondLabel.font = UIFont(name: "Arial", size: 12)
    secondLabel.text = "There"
    secondLabel.textAlignment = NSTextAlignment.Center
    secondLabel.frame = CGRectMake(0, testButton.frame.height * 0.5, testButton.frame.width, testButton.frame.height * 0.2)
    testButton.addSubview(secondLabel)
Scott
quelle
0

meine Art:

func setButtonTitle(title: String, subtitle: String, button: UIButton){
        //applying the line break mode
        button.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping;
        let title = NSMutableAttributedString(string: title, attributes: Attributes.biggestLabel)
        let subtitle = NSMutableAttributedString(string: subtitle, attributes: Attributes.label)
        let char = NSMutableAttributedString(string: "\n", attributes: Attributes.biggestLabel)
        title.append(char)
        title.append(subtitle)
        button.setAttributedTitle(title, for: .normal)
    }
Nastassie
quelle
0

Die vorgeschlagenen Lösungen haben für mich leider nicht funktioniert, als ich eine mehrzeilige Schaltfläche in einer CollectionView haben wollte. Dann zeigte mir ein Kollege eine Problemumgehung, die ich teilen wollte, falls jemand das gleiche Problem hat - hoffe, das hilft! Erstellen Sie eine Klasse, die von UIControl erbt, und erweitern Sie sie um eine Bezeichnung, die sich dann ähnlich wie eine Schaltfläche verhält.

class MultilineButton: UIControl {

    let label: UILabel = {
        $0.translatesAutoresizingMaskIntoConstraints = false
        $0.numberOfLines = 0
        $0.textAlignment = .center
        return $0
    }(UILabel())

    override init(frame: CGRect) {
        super.init(frame: frame)

        addSubview(label)

        NSLayoutConstraint.activate([
            label.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
            label.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor),
            label.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor),
            label.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor)
        ])
    }

    override var isHighlighted: Bool {
        didSet {
            backgroundColor = backgroundColor?.withAlphaComponent(isHighlighted ? 0.7 : 1.0)
            label.textColor = label.textColor.withAlphaComponent(isHighlighted ? 0.7 : 1.0)
        }
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
Mitemmetim
quelle