Bagaimana Anda menambahkan teks multi-baris ke tombol UIB?

368

Saya memiliki kode berikut...

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

... idenya adalah bahwa saya dapat memiliki teks multi-baris untuk tombol, tetapi teks selalu dikaburkan oleh backgroundImage dari UIButton. Panggilan logging untuk menunjukkan subview tombol menunjukkan bahwa UILabel telah ditambahkan, tetapi teks itu sendiri tidak dapat dilihat. Apakah ini bug di UIButton atau saya melakukan sesuatu yang salah?

Owain Hunt
sumber
7
button.titleLabel?.numberOfLines = 0
ma11hew28
2
Catatan untuk QA yang sangat lama ini, dalam Xcode modern SANGAT HANYA, PILIH "ATTRIBUTED TEXT" dan kemudian sepele, pilih "wrap karakter".
Fattie
Lihat juga jawaban terbaru untuk pertanyaan serupa.
ToolmakerSteve
lihat jawaban ini (multi-baris, lebar pas, tinggi pas) untuk teks tombol stackoverflow.com/a/59211399/7523163
Hamid Reza Ansari

Jawaban:

676

Untuk iOS 6 dan di atasnya, gunakan yang berikut ini untuk memungkinkan beberapa baris:

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

Untuk iOS 5 dan di bawah ini gunakan yang berikut untuk memungkinkan beberapa baris:

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

2017, untuk iOS9 maju ,

secara umum, lakukan saja dua hal ini:

  1. pilih "Teks yang Dikaitkan"
  2. pada "Line Break" pilih "Word Wrap"
jessecurry
sumber
5
Harap perhatikan bahwa tugas ini sudah tidak berlaku lagi di iOS 6. Lihat jawaban di bawah ini oleh @NiKKi untuk sintaks yang diperbarui.
Aaron Brager
6
Asal tahu saja: ini tidak berfungsi jika Anda menggunakan NSAttributedString
The dude
29
Sebenarnya, tambahkan saja button.titleLabel.numberOfLines = 0; Itu akan membuat garis tidak terbatas. Dan button.titleLabel.textAlignment = NSTextAlignmentLeft; jika Anda ingin teks yang dibenarkan kiri sebagai judul dipusatkan secara default.
RyJ
4
Dengan cepatbutton.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
Robert
1
Terima kasih @Robert untuk solusi cepatnya. Bisa juga menggunakan inferensi dan menghilangkan NSLineBreakMode, seperti: button.titleLabel?.lineBreakMode = .ByWordWrapping.
mjswensen
145

Jawaban yang dipilih sudah benar tetapi jika Anda lebih suka melakukan hal semacam ini di Interface Builder Anda dapat melakukan ini:

foto

Adam Waite
sumber
58
Terima kasih kepada diri saya yang berusia 24 tahun karena menulis jawaban ini, dari diri saya yang berusia 28 tahun.
Adam Waite
5
Dan untuk tinggal dengan Interface Builder hanya setup, satu harus menetapkan titleLabel.textAlignmentdengan Numbernilai 1di User Defined Runtime Attributeduntuk membuat teks berpusat
AnthoPak
2
Terima kasih untuk dirimu yang berusia 28 tahun dari diriku yang berumur 24 tahun!
Daniel Springer
59

Jika Anda ingin menambahkan tombol dengan judul di tengah dengan beberapa baris, setel pengaturan Pembuat Antarmuka Anda untuk tombol:

[ sini]

pengguna5440039
sumber
Bisakah Anda menambahkan deskripsi tekstual tentang bagaimana mencapai ini. Sebuah gambar bagus, tetapi jika tidak tersedia jawaban Anda tidak akan berguna.
Rory McCrossan
1
@RoryMcCrossan Hai, saya menambahkan gambar di atas. Bisakah kamu melihatnya? Harap dicatat, Xcode 7 masih bermasalah sehingga judul tombol mungkin hilang. Namun, begitu Anda menjalankan aplikasi, Anda akan mendapatkan hasil yang diinginkan.
user5440039
2
Ini adalah jawaban terbaik di utas ini, sebenarnya. Bekerja segera dan menampilkan teks terpusat dari IB. Terima kasih!
RainCast
@ user5440039 Terima kasih atas jawaban yang bagus. Tidak perlu menambahkan deskripsi tekstual.
Fattie
54

Untuk IOS 6:

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

Sebagai

UILineBreakModeWordWrap and UITextAlignmentCenter

sudah tidak digunakan lagi di iOS 6 dan seterusnya ..

NiKKi
sumber
Di NSText.hdalam Foundationada tidak ada yang ditambahkan ditambahkan. Ini tersedia dari 6.0 tetapi tidak usang.
Alex Cio
In swift: button.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping button.titleLabel?.textAlignment = NSTextAlignment.Center
jcity
30

Untuk menyatakan kembali saran Roger Nolan, tetapi dengan kode eksplisit, ini adalah solusi umum:

button.titleLabel?.numberOfLines = 0
baudot
sumber
21

SWIFT 3

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

Di Xcode 9.3 Anda bisa melakukannya dengan menggunakan storyboard seperti di bawah ini,

masukkan deskripsi gambar di sini

Anda perlu mengatur textignign judul tombol ke tengah

button.titleLabel?.textAlignment = .center

Anda tidak perlu mengatur teks judul dengan baris baru (\ n) seperti di bawah ini,

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

Cukup atur judul,

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

Inilah hasilnya,

masukkan deskripsi gambar di sini

Nazrul Islam
sumber
myButton.titleLabel.textAlignment = NSTextAlignmentCenterpernyataan juga dibutuhkan.
tounaobun
11

Ada cara yang jauh lebih mudah:

someButton.lineBreakMode = UILineBreakModeWordWrap;

(Edit untuk iOS 3 dan yang lebih baru :)

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
Valerii Hiora
sumber
4
UIButton.lineBreakMode sudah tidak digunakan lagi di 3.0, jadi itu bukan pilihan yang baik.
Christopher Pickslay
2
lineBreakMode hanya ditinggalkan sebagai properti langsung dari UIButton. Kami diarahkan ke "Gunakan properti lineBreakMode dari titleLabel sebagai gantinya." Saya mengedit jawaban Valerii sesuai. Itu masih pilihan yang bagus.
Wienke
11

Rata kiri di iOS7 dengan pembayaran otomatis:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
neoneye
sumber
9

Saya mempunyai masalah dengan tata letak otomatis, setelah mengaktifkan multi-line hasilnya seperti ini: jadi ukurannya tidak mempengaruhi ukuran tombol yang saya tambahkan berdasarkan (dalam hal ini contentEdgeInsets adalah (10, 10, 10, 10 ) setelah menelepon : semoga membantu Anda (cepat 5.0):
masukkan deskripsi gambar di sini
titleLabel
ConstraintscontentEdgeInsets
makeMultiLineSupport()
masukkan deskripsi gambar di sini

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

}
Amir Khorsandi
sumber
Berfungsi sempurna di swift 5. Saya juga menambahkan fungsi saya ke teks tengah tombol. func centerTextInButton () {guard let titleLabel = titleLabel else {return} titleLabel.textAlignment = .center}
ShadeToD
Terima kasih. Itu solusi yang bagus.
Eselon
Saya menemukan menambahkan kendala tidak perlu, hanya mengatur teks setelah lineBreakMode / textAlignment / numberOfLines diatur. Dan juga mengatur titleEdgeInsets untuk inset atas dan bawah.
Bill Chan
@BillChan sayangnya itu tidak berfungsi dalam semua kasus
Amir Khorsandi
7

Pertama-tama, Anda harus menyadari bahwa UIButton sudah memiliki UILabel di dalamnya. Anda dapat mengaturnya menggunakan –setTitle:forState:.

Masalah dengan contoh Anda adalah bahwa Anda perlu mengatur numberOfLinesproperti UILabel menjadi selain nilai default-nya 1. Anda juga harus meninjau lineBreakModeproperti tersebut.

Rog
sumber
Saya mengetahui properti judul, tetapi sejauh yang saya tahu tidak mungkin untuk mengaturnya untuk menggunakan lebih dari satu baris, maka pendekatan ini. Jika saya menonaktifkan backgroundImage, UILabel saya muncul, yang bagi saya menyarankan bug di bringSubviewToFront, atau UIButton sendiri.
Owain Hunt
4

Bagi mereka yang menggunakan storyboard Xcode 4, Anda dapat mengklik tombol, dan di sebelah kanan panel Utilities di bawah Attributes Inspector, Anda akan melihat opsi untuk Line Break. Pilih Word Wrap, dan Anda harus siap.

Mendongkrak
sumber
4

Jawaban di sini memberi tahu Anda cara mencapai judul tombol multiline secara terprogram.

Saya hanya ingin menambahkan bahwa jika Anda menggunakan storyboard, Anda dapat mengetik [Ctrl + Enter] untuk memaksa baris baru pada bidang judul tombol.

HTH

pengguna2338871
sumber
4

Anda harus menambahkan kode ini:

buttonLabel.titleLabel.numberOfLines = 0;
Pablo Blanco
sumber
3

Adapun gagasan Brent tentang menempatkan judul UILabel sebagai pandangan saudara, menurut saya itu bukan ide yang sangat bagus. Saya terus berpikir dalam masalah interaksi dengan UILabel karena peristiwa sentuhannya tidak melewati pandangan UIButton.

Di sisi lain, dengan UILabel sebagai subview dari UIButton, saya cukup nyaman mengetahui bahwa acara sentuh akan selalu disebarkan ke superview UILabel.

Saya memang mengambil pendekatan ini dan tidak melihat adanya masalah yang dilaporkan dengan backgroundImage. Saya menambahkan kode ini dalam -titleRectForContentRect: dari subkelas UIButton tetapi kode tersebut juga dapat ditempatkan dalam menggambar rutin superview UIButton, yang dalam hal ini Anda harus mengganti semua referensi untuk diri sendiri dengan variabel 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;
}

Saya mengambil waktu dan menulis lebih banyak tentang ini di sini . Di sana, saya juga menunjukkan solusi yang lebih pendek, meskipun tidak cukup cocok dengan semua skenario dan melibatkan beberapa pandangan pribadi peretasan. Juga di sana, Anda dapat mengunduh subkelas UIButton yang siap digunakan.

jpedroso
sumber
3

Jika Anda menggunakan tata-letak otomatis di iOS 6 Anda mungkin juga perlu mengatur preferredMaxLayoutWidthproperti:

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

Mengatur lineBreakMode ke NSLineBreakByWordWrapping (baik dalam IB atau kode) membuat label tombol multiline, tetapi tidak memengaruhi bingkai tombol.

Jika tombol memiliki judul dinamis, ada satu trik: letakkan UILabel tersembunyi dengan font yang sama dan ikat tingginya dengan tinggi tombol dengan tata letak; ketika mengatur teks ke tombol dan label dan autolayout akan membuat semua berfungsi.

Catatan

Tinggi ukuran intrinsik tombol satu-baris lebih besar daripada label, sehingga untuk mencegah penyusutan tinggi label itu vertikal Content Hugging Priority harus lebih besar daripada Resistensi Kompresi Konten vertikal tombol.

Varrry
sumber
3

Di Swift 5.0 dan Xcode 10.2

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

Dalam panggilan ViewController Anda seperti ini

button.btnMultipleLines()//This is your button
iOS
sumber
3

Swift 5, Untuk teks multi-baris dalam UIButton

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

Ini bekerja dengan sempurna.

Tambahkan untuk menggunakan ini dengan file konfigurasi seperti Plist, Anda perlu menggunakan CDATA untuk menulis judul multiline, seperti ini:

<string><![CDATA[Line1
Line2]]></string>
makiko_fly
sumber
2

Jika Anda menggunakan tata-letak otomatis.

button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.numberOfLines = 2
Sourabh Sharma
sumber
2

cepat 4.0

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

Saat ini, jika Anda benar-benar membutuhkan hal semacam ini agar dapat diakses di pembuat antarmuka berdasarkan kasus per kasus, Anda dapat melakukannya dengan ekstensi sederhana seperti ini:

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

Kemudian Anda bisa mengatur numberOfLines sebagai atribut pada setiap subkelas UIButton atau UIButton seolah-olah itu adalah label. Hal yang sama berlaku untuk seluruh host nilai-nilai lain yang biasanya tidak dapat diakses, seperti jari-jari sudut lapisan tampilan, atau atribut bayangan yang dilemparkannya.

Abu
sumber
0

Gulung kelas tombol Anda sendiri. Sejauh ini solusi terbaik dalam jangka panjang. UIButton dan kelas-kelas UIKit lainnya sangat membatasi cara Anda dapat menyesuaikannya.


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

self.btnError.titleLabel?.textAlignment = .center

self.btnError.setTitle("Title", for: .normal)
Modi Urvish
sumber
0

Saya memasukkan jawaban jessecurry ke dalam STAButton yang merupakan bagian dari perpustakaan open source STAC saya . Saat ini saya menggunakannya dalam salah satu aplikasi yang saya kembangkan dan berfungsi untuk kebutuhan saya. Jangan ragu untuk membuka masalah tentang cara memperbaikinya atau mengirim saya permintaan tarik.

Stunner
sumber
0

Untuk memperbaiki jarak label judul ke tombol, atur titleEdgeInsets dan properti lainnya sebelum setTitle:

    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 Saya menguji setting titleLabel? .TextAlignment tidak perlu dan judulnya rata .natural.

Bill Chan
sumber
-4

Meskipun tidak apa-apa untuk menambahkan subview ke kontrol, tidak ada jaminan itu akan berfungsi, karena kontrol mungkin tidak mengharapkannya ada di sana dan karenanya mungkin berperilaku buruk. Jika Anda dapat melakukannya, cukup tambahkan label sebagai tampilan saudara dari tombol dan atur bingkainya sehingga tumpang tindih tombol; selama itu diatur untuk muncul di atas tombol, tidak ada tombol yang dapat dilakukan akan mengaburkannya.

Dengan kata lain:

[button.superview addSubview:myLabel];
myLabel.center = button.center;
Brent Royal-Gordon
sumber
2
Tolong, jika Anda menyarankan pendekatan jelek semacam ini setidaknya jangan membuat kesalahan dalam contoh kode Anda :). Label tidak boleh memiliki tombol tengah yang sama dengan jika subview. Gunakan myLabel.frame = button.bounds; atau myLabel.center = cgPointMake (button.frame.size.with * 0.5, button.frame.size.height * 0.5)
JakubKnejzlik
1
@GrizzlyNetch Saya secara khusus menyarankan untuk tidak menambahkannya sebagai subview tombol. addSubview:di sini menambahkannya ke buttonsuperview, sehingga menjadikannya saudara tombol, sehingga mencocokkan pusat mereka benar.
Brent Royal-Gordon
Ah, kesalahanku! Anda benar, saya telah melewatkan fakta "kecil" yang ada di superview: D ... maaf :)
JakubKnejzlik
Tidak persis apa yang diminta, solusi ini akan menjadi cara yang buruk untuk mengimplementasikan pertanyaan karena tombol elemen memiliki judul.
Pablo Blanco
Ini saran yang masuk akal di iPhone OS 2.0. Ada banyak cara yang lebih baik untuk melakukannya sekarang. : ^)
Brent Royal-Gordon