Label multiline di UIStackView

154

Saat meletakkan label multiline (dengan linebreak diatur ke Word Wrap) ke dalam tampilan stack, label segera kehilangan linebreak dan menampilkan teks label dalam satu baris saja.

Mengapa ini terjadi dan bagaimana cara mempertahankan label multiline dalam tampilan tumpukan?

Anugerah
sumber
1
Apakah Anda menetapkan jumlah baris ke 0?
dasdom
Apakah Anda menemukan jawaban?
Brenden

Jawaban:

204

Jawaban yang benar ada di sini:
https://stackoverflow.com/a/43110590/566360


  1. Sematkan bagian UILabeldalam UIView(Editor -> Sematkan Dalam -> Tampilan)
  2. Gunakan batasan untuk menyesuaikan UILabeldengan UIView(misalnya, ruang tambahan, ruang atas, dan ruang utama untuk batasan tampilan super)

The UIStackViewakan meregangkan UIViewsesuai dengan benar, dan UIViewakan membatasi UILabeluntuk beberapa baris.

Andy
sumber
36
Ini sangat bodoh tetapi berhasil! Terima kasih sobat ! Mungkin suatu hari Apple akan merilis sesuatu yang tidak setengah rusak di SDK mereka ...
Guillaume L.
1
Oh man! Anda adalah penyelamat! Saya sudah berjam-jam :) Ingat juga untuk mengatur garis ke 0 di Atribut Inspektur, hilang begitu saja.
absin
8
ini solusinya, solusi yang tepat ada di sini stackoverflow.com/a/43110590/566360
vietstone
2
Cukup bagi saya hanya untuk mengubah perataan horizontal ke tengah. Tidak UIViewperlu shenanigans.
shim
1
@Lucien inilah yang dikatakan dalam jawaban ini. tetapi jawaban yang benar ada di sini: stackoverflow.com/a/43110590/566360
Andy
144

Untuk tampilan tumpukan horizontal yang memiliki UILabelsalah satu dari pandangannya, di Interface Builder atur terlebih dahulu label.numberOfLines = 0. Ini harus memungkinkan label memiliki lebih dari 1 baris. Ini awalnya gagal untuk saya ketika tampilan stack sudah stackView.alignment = .fill. Untuk membuatnya bekerja cukup atur stackView.alignment = .center. Label sekarang dapat diperluas ke beberapa baris di dalam UIStackView.

The Apple dokumentasi mengatakan

Untuk semua penyejajaran kecuali penyejajaran isian, tampilan tumpukan menggunakan properti Ukuran Konten intrinsik dari setiap tampilan yang diatur saat menghitung ukurannya tegak lurus terhadap sumbu tumpukan

Catat kata kecuali di sini. Ketika .filldigunakan, horizontal UIStackViewTIDAK mengubah ukurannya sendiri secara vertikal menggunakan ukuran tampilan sub-tersusun.

pbm
sumber
3
Ini adalah solusi tepat tanpa peretasan. Membaca dokumen selalu terbayar!
Islam Q.
3
Ini harus menjadi solusi yang diterima. Dengan solusi UIView, teks UILabel melayang di atas subview lain dalam kasus saya.
14
Sebenarnya tidak berfungsi ... Saya punya 3 label di stackview saya. Saya telah menetapkan garis ke nol dan menyejajarkan ke pusat ... Saya masih melihat label terpotong.
MatterGoal
11
Ini adalah .alignmentdari UIStackView yang Anda harus siap untuk apa pun kecuali .fill tidak UILabel, yang sedikit membingungkan dalam contoh yang diberikan label.alignment = .center. Saya pikir ini seharusnyastackView.alignment = .center
ae14
2
Tetapi bagaimana saya bisa membuat beberapa baris UILableView bekerja di StackView vertikal?
DàChún
42
  • Pertama-tama atur nomor label garis ke 0
  • Tampilan tumpukan masih tidak akan tumbuh multiLinekecuali Anda memberinya lebar tetap. Ketika kami memperbaiki lebarnya, maka ia akan pecah menjadi multiline saat lebar itu tercapai seperti yang ditunjukkan:

rekaman layar

Jika kita tidak memberikan lebar yang tetap pada tampilan stack maka semuanya menjadi ambigu. Berapa lama tampilan tumpukan tumbuh dengan label (jika nilai label dinamis)?

Semoga ini bisa memperbaiki masalah Anda.

Irfan
sumber
3
Bagaimana jika lebar tampilan tumpukan tidak tetap tetapi sebaliknya proporsional dengan lebar perangkat (yaitu superview).
OutOnAWeekend
Ya, kami juga dapat memiliki lebar yang proporsional. Intinya adalah jika label harus putus setelah beberapa lebar apa pun itu tetapi perlu didefinisikan.
Irfan
@AnandKumar Anda dapat menentukan preferredMaxLayoutWidthdalam viewDidLayoutSubviewsuntuk label Anda UIViewControlleratau layoutSubviewsjika Anda subkelas UIView.
Shyngys Kassymov
4
Ini seharusnya jawaban yang diterima, inti dari stackview adalah untuk tidak harus menambahkan batasan antara stackview dan elemen-elemennya ...
Honey
4
Memberikan nilai tetap mengalahkan tujuan autolayout
Islam Q.
17

Pengaturan preferMaxLayoutWidth ke UILabel bekerja untuk saya

self.myLabel.preferredMaxLayoutWidth = self.bounds.size.width;
Pablo Martinez
sumber
3
Ini jawaban yang benar di buku saya. Ketika Anda mengacaukan UILabel's dan perlu menangani beberapa baris, Anda benar-benar harus memberikannyaMaxLayoutWidth yang disukai. Ini mungkin berhasil tanpanya, tetapi segalanya bisa menjadi agak funky dengan sangat cepat tanpanya.
Mof
2
Semua mencoba semua jawaban dan semuanya salah kecuali jawaban Anda. Terima kasih!
levan
Ini menyelesaikan masalah saya dengan sempurna dan merasa kurang hacky, terima kasih.
Ethan Zhao
Terima kasih atas jawaban anda! Dalam kasus saya penyelarasan stackView saya sudah diatur ke .centerdan saya benar-benar tidak perlu label saya di dalam UIView.
Fariza Zhumat
12

Cukup atur jumlah baris ke 0 di Inspektur atribut untuk label. Ini akan bekerja untuk Anda.

masukkan deskripsi gambar di sini

technerd
sumber
12
Untuk stackView vertikal, Anda perlu mengatur Distribusi agar "Isi" agar ini berfungsi.
SnoopyProtocol
2
Mengatur Distribusi ke "Isi" adalah kunci untuk memperbaiki.
Dylan Moore
Saya menemukan bahwa untuk UIStackView vertikal, saya harus menetapkan batasan atas dan bawah untuk anak UILabel untuk diperluas dan menampilkan semua teks.
bruce1337
8

Setelah mencoba semua saran di atas saya tidak menemukan perubahan properti diperlukan untuk UIStackView. Saya baru saja mengubah properti dari label UIL sebagai berikut (Label sudah ditambahkan ke tampilan tumpukan vertikal):

Contoh Swift 4:

    [titleLabel, subtitleLabel].forEach(){
        $0.numberOfLines = 0
        $0.lineBreakMode = .byWordWrapping
        $0.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
    }
Bill Chan
sumber
5

Trik sulap bagi saya adalah mengatur a widthAnchorke UIStackView.

Pengaturan leadingAnchordan trailingAnchortidak akan berfungsi, tetapi pengaturan centerXAnchordan widthAnchormembuat tampilan UILabel dengan benar.

Skoua
sumber
4

iOS 9+

Panggil [textLabel sizeToFit]setelah mengatur teks UILabel.

sizeToFit akan menata ulang label multiline menggunakan preferMaxWidth. Label akan mengubah ukuran stackView, yang akan mengubah ukuran sel. Tidak ada kendala tambahan selain menyematkan tampilan tumpukan ke tampilan konten.

aumansoftware
sumber
4

Berikut adalah contoh lengkap dari vertikal yang UIStackViewterbuat dari multiline UILabels dengan ketinggian otomatis.

Bungkus label berdasarkan lebar stackview dan tinggi stackview didasarkan pada tinggi label yang terbungkus. (Dengan pendekatan ini Anda tidak perlu menyematkan label dalam a UIView.) (Swift 5, iOS 12.2)

masukkan deskripsi gambar di sini

// A vertical stackview with multiline labels and automatic height.
class ThreeLabelStackView: UIStackView {
    let label1 = UILabel()
    let label2 = UILabel()
    let label3 = UILabel()

    init() {
        super.init(frame: .zero)
        self.translatesAutoresizingMaskIntoConstraints = false
        self.axis = .vertical
        self.distribution = .fill
        self.alignment = .fill

        label1.numberOfLines = 0
        label2.numberOfLines = 0
        label3.numberOfLines = 0
        label1.lineBreakMode = .byWordWrapping
        label2.lineBreakMode = .byWordWrapping
        label3.lineBreakMode = .byWordWrapping
        self.addArrangedSubview(label1)
        self.addArrangedSubview(label2)
        self.addArrangedSubview(label3)

        // (Add some test data, a little spacing, and the background color
        // make the labels easier to see visually.)
        self.spacing = 1
        label1.backgroundColor = .orange
        label2.backgroundColor = .orange
        label3.backgroundColor = .orange
        label1.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi."
        label2.text = "Hello darkness my old friend..."
        label3.text = "When I wrote the following pages, or rather the bulk of them, I lived alone, in the woods, a mile from any neighbor, in a house which I had built myself, on the shore of Walden Pond, in Concord, Massachusetts, and earned my living by the labor of my hands only."
    }

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

Berikut adalah contoh ViewControlleryang menggunakannya.

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let myLabelStackView = ThreeLabelStackView()
        self.view.addSubview(myLabelStackView)

        // Set stackview width to its superview.
        let widthConstraint  = NSLayoutConstraint(item: myLabelStackView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view, attribute: NSLayoutConstraint.Attribute.width, multiplier: 1, constant: 0)
        self.view.addConstraints([widthConstraint])
    }
}
zekel
sumber
3

Tambahkan UIStackViewproperti,

stackView.alignment = .fill
stackView.distribution = .fillProportionally
stackView.spacing = 8.0
stackView.axis = .horizontal

Alih-alih menambahkan label di dalam UIViewyang tidak diperlukan. Jika Anda menggunakan di dalam UITableViewCelltolong, muat ulang data secara rotasi.

Sagar Daundkar
sumber
3

Berikut ini adalah penerapan Playground label multi-line dengan garis istirahat di dalam a UIStackView. Tidak perlu menyematkan bagian UILabeldalam apa pun dan telah diuji dengan Xcode 9.2 dan Swift 4. Semoga bermanfaat.

import UIKit
import PlaygroundSupport

let containerView = UIView()
containerView.frame = CGRect.init(x: 0, y: 0, width: 400, height: 500)
containerView.backgroundColor = UIColor.white

var label = UILabel.init()
label.textColor = .black
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "This is an example of sample text that goes on for a long time. This is an example of sample text that goes on for a long time."

let stackView = UIStackView.init(arrangedSubviews: [label])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.distribution = .fill
stackView.alignment = .fill
containerView.addSubview(stackView)
stackView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
stackView.widthAnchor.constraint(equalTo: containerView.widthAnchor).isActive = true
stackView.heightAnchor.constraint(equalTo: containerView.heightAnchor).isActive = true

PlaygroundPage.current.liveView = containerView
Jared
sumber
1

Tata letak sistem harus mencari tahu asal, lebar dan tinggi untuk menggambar subview, dalam hal ini semua subview Anda memiliki prioritas yang sama, saat itu membuat konflik, sistem tata letak tidak diketahui ketergantungan antara tampilan, yang mana menggambar pertama, kedua dan seterusnya

Mengatur kompresi subview tumpukan akan menyelesaikan masalah dengan beberapa baris, tergantung pada tampilan tumpukan Anda secara horizontal atau vertikal dan yang Anda inginkan menjadi beberapa baris. stackOtherSubviews .setContentCompressionResistancePriority(.defaultHight, for: .horizontal) lblTitle.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

Trung Phan
sumber
0

Dalam kasus saya, saya mengikuti saran sebelumnya, tetapi teks saya masih terpotong menjadi satu baris meskipun hanya dalam lanskap. Ternyata, saya menemukan \0karakter nol yang tidak terlihat dalam teks label yang merupakan biang keladinya. Itu pasti telah diperkenalkan di samping simbol tanda hubung yang saya masukkan. Untuk melihat apakah ini juga terjadi dalam kasus Anda, gunakan View Debugger untuk memilih label Anda dan memeriksa teksnya.

Jordan H
sumber
0

Xcode 9.2:

Cukup atur jumlah baris ke 0. Storyboard akan terlihat aneh setelah mengatur ini. Jangan khawatir menjalankan proyek. Saat menjalankan semuanya akan mengubah ukuran sesuai pengaturan papan cerita Anda. Saya pikir jenis bug di storyboard. masukkan deskripsi gambar di sini

Tips: Atur "jumlah liner ke 0" di yang terakhir. atur ulang ketika Anda ingin mengedit beberapa tampilan lain dan atur ke 0 setelah mengedit.

masukkan deskripsi gambar di sini

Surendra Kumar
sumber
0

Apa yang berhasil untuk saya!

stackview: alignment: fill, distribusi: fill, kendala proporsional width ke superview ex. 0.8,

label: pusat, dan garis = 0

Michał Ziobro
sumber
0

Untuk siapa saja yang masih tidak bisa membuatnya bekerja. Coba tetapkan Autoshrink dengan Skala Font minimum pada UILabel itu.

Tangkapan layar UILabel Pengaturan autoshrink

Michal Mondík
sumber
Pertimbangkan untuk meningkatkan jawaban Anda dengan contoh kode.
fridoo
1
@fridoo Menambahkan tangkapan layar pengaturan.
Michal Mondík
0

Ini hampir seperti @ Jawaban Andy, tetapi Anda dapat menambahkan UILabelekstra Anda UIStackview, vertikal bekerja untuk saya.

Zaporozhchenko Oleksandr
sumber
0

Bagi saya, masalahnya adalah bahwa ketinggian tampilan tumpukan terlalu pendek. Tampilan label dan stack diatur dengan benar untuk memungkinkan label memiliki beberapa baris, tetapi label adalah korban kompresi konten pertama yang digunakan tampilan stack untuk mendapatkan ketinggiannya cukup kecil.

Luke
sumber