UILabel tidak otomatis menciutkan teks agar sesuai dengan ukuran label

119

Saya memiliki masalah aneh ini, dan saya mengatasinya selama lebih dari 8 jam sekarang .. Bergantung pada situasi saya harus menghitung UILabelsukuran secara dinamis,
misalnya
saya UIViewControllermenerima sebuah acara dan saya mengubah UILabelsukuran. dari yang lebih besar ke yang lebih kecil. Ukuran saya UILabelmenjadi lebih kecil dan saya mendapatkan ukuran yang dibutuhkan yang benar, tetapi teks dalam saya UILabeltetap sama, ukuran font yang sama dan lain-lain. Saya membutuhkan font untuk menjadi lebih kecil, agar seluruh teks sesuai UILabel. Jadi pertanyaannya adalah bagaimana membuat teks agar sesuai dengan label saya autoshrinkingatau sesuatu seperti itu?

Di saya xib, UILabels autoshrinkdicentang, juga jumlah baris diatur ke 0, dan juga string saya memiliki simbol baris baru (\ n), dan saya telah memilih linebreakmode ke wordwrap. Mungkin ada orang yang berada dalam situasi yang sama seperti saya sekarang, dan dapat membantu saya? Saya akan sangat menghargai itu.

Terima kasih sebelumnya!

EDIT: UILabel ukuran font minimum diatur ke 10

Lukas
sumber
berapa ukuran minimum font Anda untuk label yang Anda setel, silakan tambahkan.
AJPatel

Jawaban:

159

Jika Anda masih mencari solusi yang lebih baik, saya pikir inilah yang Anda inginkan:

Nilai Boolean yang menunjukkan apakah ukuran font harus diperkecil agar sesuai dengan string judul ke dalam persegi panjang pembatas label (properti ini hanya efektif jika numberOfLinesproperti disetel ke 1).

Saat menyetel properti ini, minimumScaleFactorHARUS disetel juga (default yang baik adalah 0,5).

Cepat

var adjustsFontSizeToFitWidth: Bool { get set }

Objective-C

@property(nonatomic) BOOL adjustsFontSizeToFitWidth;

Nilai Boolean yang menunjukkan apakah spasi antar huruf harus disesuaikan agar pas dengan string di dalam persegi panjang batas label.

Cepat

var allowsDefaultTighteningForTruncation: Bool { get set }

Objective-C

@property(nonatomic) BOOL allowsDefaultTighteningForTruncation;

Sumber .

lester
sumber
18
Sebagai sidenote, minimumFontSizetidak digunakan lagi di iOS 6.0. Gunakan minimumScaleFactorsebagai gantinya.
lester
14
Ya, penyusutan otomatis tidak berfungsi untuk beberapa baris di UILabel. Coba bayangkan ini: Anda memiliki teks dengan banyak baris, Anda ingin mengecilkannya agar "pas" dengan lebarnya. Jadi, haruskah itu mengecilkan seluruh teks agar pas dalam satu baris, atau kata-kata tetap dalam baris yang sama dan menyusut agar pas dengan setiap lebar? Yang terakhir adalah kasus yang paling umum, tetapi jangan lupa bahwa kata-kata juga diatur untuk mengatur dirinya sendiri dalam beberapa baris. Meskipun pengaturan otomatis teks dinonaktifkan, Anda harus berhadapan dengan setiap baris teks yang memiliki ukuran font berbeda, karena tidak setiap kata akan pas dengan lebarnya.
lester
2
Saya pikir jawaban dengan Kategori di sini cukup bagus, bahkan mungkin itu yang Anda terapkan. Ini jelas merupakan sesuatu yang hilang di Apple API, atau mungkin mereka tidak melihat penyusutan seharusnya menjadi kasus penggunaan umum untuk beberapa baris teks statis .
lester
1
ya itu poin yang bagus, tapi bagaimanapun, saya pikir jika saya mengatur jumlah baris menjadi 0, itu semacam pernyataan yang jelas bahwa mungkin ada satu atau lebih baris. Dan autoshrink bisa ditentukan oleh nomor baris yang kurasa .. Tapi bagaimanapun, terima kasih telah membereskan semuanya. Saya pikir saya melakukan sesuatu yang salah. Kategorie adalah ide yang bagus, saya rasa saya akan melakukannya di proyek lain di mana saya akan membutuhkan ini. Hargai bantuan Anda, semoga berhasil;)
Lukas
4
@ lester Ini harus menyusut sehingga seluruh teks terlihat dalam jumlah baris yang dideklarasikan untuk label yang diberikan dimensinya saat ini. Tidak perlu mencoba membuat setiap baris berukuran berbeda. Saya benar-benar terkejut tidak bisa memahami ini. Jadi jika saya memiliki (berpotensi) string panjang untuk menampilkan aku bisa baik memiliki beberapa baris atau memilikinya auto-ukuran, tidak keduanya. Itu sangat indah.
devios1
125

Ini adalah bagaimana saya mendapatkan Autoshrinkkerja UILabel (terutama untuk ketinggian pemasangan font label di perangkat 4s dari 6s Plus Storyboard) di iOS 9.2, Xcode 7.2 ...

masukkan deskripsi gambar di sini

  • Jumlah baris adalah 0
  • Jeda Baris: Klip
  • Autoshrink: Skala Font Minimum 0.25
ohho
sumber
15
Ini adalah 3 bahan yang diperlukan agar label benar-benar menyusut, saya kehilangan pengaturan jeda baris klip. Selain itu, jika berdekatan dengan label lain (yang juga mungkin menyusut otomatis) maka prioritas kompresi / hugging perlu disetel atau batasan lebar atau tinggi eksplisit diberikan. Ini harus menjadi jawaban yang diterima saat ini.
Korey Hinton
3
Jumlah baris berhasil untuk saya! Terima kasih
Michael
Pastikan label Anda memiliki semua batasan terutama di depan dan di belakang.
Mashhadi
2
Saya telah mencoba dengan opsi yang sama di Xcode8 dan ternyata tidak berfungsi. Tolong bantu saya jika ada yang punya ide tentang ini.
Ganesh
75

minimumFontSize tidak digunakan lagi di iOS 6.

Jadi gunakan minimumScaleFactorsaja minmimumFontSize.

lbl.adjustsFontSizeToFitWidth = YES
lbl.minimumScaleFactor = 0.5

Cepat 5

lbl.adjustsFontSizeToFitWidth = true
lbl.minimumScaleFactor = 0.5
SwiftiSwift
sumber
Jawabannya bagus. Memecahkan masalah saya. Terima kasih
Abdul Yasin
1
@AntonMatosov, tidak, tidak!
Iulian Onofrei
2
Ya, memang (sekarang) - jika Anda juga menyetel jeda baris ke Truncate Tail alih-alih Word Wrap ...
TheEye
21

juga solusi saya adalah boolean label.adjustsFontSizeToFitWidth = YES; TAPI. Anda harus di Builder antarmuka Word Wrapping beralih ke " CLIP ". Kemudian tautkan otomatis Label. Ini sangat penting.

loki-e
sumber
3
Hanya ketika saya mengubah dari "Word Wrap" menjadi "Clip", Autoshrink berfungsi untuk saya.
NicJ
Ketika saya mengubah bungkus kata menjadi klip, saya sebenarnya bisa mengubahnya dalam label dengan garis nol. Wah, alangkah baiknya jika ini didokumentasikan.
DesignatedNerd
12

Di Swift 3 (Secara terprogram) saya harus melakukan ini:

let lbl = UILabel()
lbl.numberOfLines = 0
lbl.lineBreakMode = .byClipping
lbl.adjustsFontSizeToFitWidth = true
lbl.minimumScaleFactor = 0.5
lbl.font = UIFont.systemFont(ofSize: 15)
Naloiko Eugene
sumber
5

Anda bisa menulis seperti

UILabel *reviews = [[UILabel alloc]initWithFrame:CGRectMake(14, 13,270,30)];//Set frame
reviews.numberOfLines=0;
reviews.textAlignment = UITextAlignmentLeft;
reviews.font = [UIFont fontWithName:@"Arial Rounded MT Bold" size:12];
reviews.textColor=[UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:0.8]; 
reviews.backgroundColor=[UIColor clearColor];

Anda dapat menghitung jumlah baris seperti itu

CGSize maxlblSize = CGSizeMake(270,9999);
CGSize totalSize = [reviews.text sizeWithFont:reviews.font 
              constrainedToSize:maxlblSize lineBreakMode:reviews.lineBreakMode];

CGRect newFrame =reviews.frame;
newFrame.size.height = totalSize.height;
reviews.frame = newFrame;

CGFloat reviewlblheight = totalSize.height;

int lines=reviewlblheight/12;//12 is the font size of label

UILabel *lbl=[[UILabel alloc]init];
lbl.frame=CGRectMake(140,220 , 100, 25);//set frame as your requirement
lbl.font=[UIFont fontWithName:@"Arial" size:20];
[lbl setAutoresizingMask:UIViewContentModeScaleAspectFill];
[lbl setLineBreakMode:UILineBreakModeClip];
lbl.adjustsFontSizeToFitWidth=YES;//This is main for shrinking font
lbl.text=@"HelloHelloHello";

Semoga ini bisa membantu Anda :-) menunggu balasan Anda

Birju
sumber
jadi jika mengatur jumlah baris ke label saya, teks akan otomatis berputar?
Lukas
jika konten Anda keluar dari lebar maka akan mengambil baris berikutnya
Birju
hai saya telah melakukan seperti yang Anda sarankan, tetapi tidak berhasil, mengapa jumlah baris akan membantu saya?
Lukas
Anda benar saya mencoba itu tidak berguna tetapi saya menemukan solusi untuk Anda lakukan seperti itu jawaban saya berikutnya
Birju
lbl.adjustsFontSizeToFitWidth = YA; Bekerja untuk saya!
Pengembang
4

Nah pada akhirnya saya tidak menemukan jawaban saya. Dan menurut saya autoshrink tidak berfungsi untuk banyak baris. Saya akhirnya menggunakan saran di tautan ini: tautan otomatis pada UILabel dengan banyak baris

Solusinya adalah dengan menghitung tinggi teks pada lebar tertentu dan jika teks lebih besar, mengecilkan ukuran font lalu lakukan hal yang sama lagi hingga tingginya sama atau kurang dari ukuran yang Anda butuhkan.

Saya tidak mengerti mengapa ini harus sangat sulit diterapkan. Jika saya melewatkan sesuatu, semua orang dipersilakan untuk mengoreksi saya :)

Lukas
sumber
Sesuai jawaban lain di sini, hal utama yang hilang adalah Anda perlu mengatur Word Wrapping ke "Clip". Ini kontra-intuitif, tetapi ini diperlukan untuk mendapatkan UILabel untuk menyusut otomatis sesuai keinginan Anda. Ini bekerja dengan UILabel multi-baris.
Duncan Babbage
4

Ini untuk Swift 3 yang menjalankan Xcode 8.2.1 (8C1002)

Solusi terbaik yang saya temukan adalah menyetel lebar tetap di Storyboard atau IB Anda pada label. Tetapkan batasan Anda dengan batasan ke margin. Di viewDidLoad Anda, tambahkan baris kode berikut:

override func viewDidLoad() {
            super.viewDidLoad()

            label.numberOfLines = 1
            label.adjustsFontSizeToFitWidth = true
            label.minimumScaleFactor = 0.5
        }

batasan label ke margin

batasan label lebar tetap ke margin

inspektur atribut

Ini berfungsi seperti pesona dan tidak meluap ke baris baru dan menyusutkan teks agar sesuai dengan lebar label tanpa masalah aneh dan berfungsi di Swift 3.

Rob Mcelvenny
sumber
4

Ini pertanyaan yang bagus, karena sepertinya itu akan menjadi bagian dari UIKitfungsionalitas bawaan atau kerangka kerja terkait sekarang. Berikut adalah contoh visual yang bagus dari pertanyaan tersebut:

Animasi mengubah ukuran font

Tidak ada cara mudah untuk mengatasinya, tetapi itu pasti mungkin. Salah satu cara untuk melakukannya adalah dengan mencoba berbagai ukuran font secara terprogram hingga Anda menemukan salah satu yang cukup dekat dengan batas tampilan. Anda dapat melakukannya dengan boundingRect()fungsi NSStringatau NSAttributedString. Sebagai contoh:

let string = "This is a test"
let infiniteSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height:CGFloat.greatestFiniteMagnitude)
let size = string.boundingRect(with: infiniteSize, options: [], attributes: [.font: UIFont.systemFont(ofSize: avgSize)] context: nil).size

Anda dapat melakukan pencarian biner agar lebih efisien daripada pendekatan brute force lengkap. Ada juga beberapa pertimbangan yang sedikit lebih terlibat, termasuk pembungkusan kata yang benar dan kinerja cache font iOS, jika Anda mencari sesuatu yang sangat kuat.

Jika Anda hanya peduli tentang menampilkan teks di layar dengan cara yang mudah, saya telah mengembangkan implementasi yang kuat di Swift, yang juga saya gunakan dalam aplikasi produksi. Ini adalah UIViewsubclass dengan penskalaan font otomatis yang efisien untuk teks input apa pun, termasuk beberapa baris. Untuk menggunakannya, Anda cukup melakukan sesuatu seperti:

let view = AKTextView()
// Use a simple or fancy NSAttributedString
view.attributedText = .init(string: "Some text here")
// Add to the view hierarchy somewhere

Itu dia! Anda dapat menemukan sumber lengkapnya di sini: https://github.com/FlickType/AccessibilityKit

Semoga ini membantu!

Kosta Eleftheriou
sumber
1
Nov 2018: Muncul FlickType dan AccessibilityKit telah menjadi pribadi atau dihapus.
Chris Paveglio
3

Di iOS 9 saya hanya perlu:

  1. Tambahkan pembatas dari kiri dan kanan label ke superview.
  2. Atur mode jeda baris ke kliping di IB.
  3. Setel jumlah baris menjadi 1 di IB.

Seseorang merekomendasikan pengaturan jumlah baris menjadi 0, tetapi bagi saya ini hanya membuat label menjadi beberapa baris ...

Nick Yap
sumber
Ini melakukan trik untuk saya. Saya baru saja memilih a UILabeldan a UITextFielddalam sel statis dan mengklik "Selesaikan Masalah Tata Letak Otomatis", dan "Tambahkan Kendala yang Hilang". Semuanya berbaris, tetapi Autoshrink perlu mengetahui jarak ke label, yang "Add Missing Constraints" tidak menambahkan batasan.
Adrian
2

Saya pikir Anda dapat menulis kode di bawah ini setelah mengalokasikan Label init

UILabel* lbl = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, 280, 50)];
lbl.text = @"vbdsbfdshfisdhfidshufidhsufhdsf dhdsfhdksbf hfsdh fksdfidsf sdfhsd fhdsf sdhfh sdifsdkf ksdhfkds fhdsf dsfkdsfkjdhsfkjdhskfjhsdk fdhsf ";
[lbl setMinimumFontSize:8.0];
[lbl setNumberOfLines:0];
[lbl setFont:[UIFont systemFontOfSize:10.0]];
lbl.lineBreakMode = UILineBreakModeWordWrap;
lbl.backgroundColor = [UIColor redColor];
[lbl sizeToFit];
[self.view addSubview:lbl];

Ini bekerja dengan saya baik-baik saja. Gunakan

iDhaval
sumber
1
terima kasih, tetapi ini tidak akan menghitung atau mengecilkan font ke minimum yang diperlukan seperti yang saya mengerti, dan juga mengapa font minimum Anda lebih besar dari biasanya?
Lukas
2

Dua tahun berlalu, dan masalah ini masih ada ...

Di iOS 8 / XCode 6.1, saya terkadang menemukan bahwa saya UILabel(dibuat di fileUITableViewCell , dengan AutoLayout dihidupkan, dan batasan fleksibel sehingga memiliki banyak ruang) tidak akan mengubah ukurannya sendiri agar sesuai dengan string teks.

Solusinya, seperti tahun-tahun sebelumnya, adalah mengatur teks, dan kemudian menelepon sizeToFit.

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    . . .
    cell.lblCreatedAt.text = [note getCreatedDateAsString];
    [cell.lblCreatedAt sizeToFit];
}

(Mendesah.)

Mike Gledhill
sumber
1

Begini cara melakukannya Misalkan messageLabel berikut adalah label yang Anda inginkan untuk mendapatkan efek yang diinginkan. Sekarang, coba baris kode sederhana ini:

    //SET THE WIDTH CONSTRAINTS FOR LABEL.
    CGFloat constrainedWidth = 240.0f;//YOU CAN PUT YOUR DESIRED ONE,THE MAXIMUM WIDTH OF YOUR LABEL.
 //CALCULATE THE SPACE FOR THE TEXT SPECIFIED.
    CGSize sizeOfText=[yourText sizeWithFont:yourFont constrainedToSize:CGSizeMake(constrainedWidth, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
    UILabel *messageLabel=[[UILabel alloc] initWithFrame:CGRectMake(20,20,constrainedWidth,sizeOfText.height)];
    messageLabel.text=yourText;
    messageLabel.numberOfLines=0;//JUST TO SUPPORT MULTILINING.
Anand
sumber
hai terima kasih atas jawaban Anda, tetapi saya tidak perlu menghitung tinggi label, saya memiliki ukuran tetap, dan tergantung pada itu font saya harus lebih kecil jika diperlukan.
Lukas
1

tidak bekerja jika numberOfLines > 1 apa yang saya lakukan membuat kondisi seperti ini-

if(lblRecLocation.text.length > 100)
    lblRecLocation.font = [UIFont fontWithName:@"app_font_name" size:10];
Vaibhav Saran
sumber
0

Datang terlambat ke pesta, tetapi karena saya memiliki persyaratan tambahan untuk memiliki satu kata per baris, penambahan satu ini berhasil untuk saya:

label.numberOfLines = [labelString componentsSeparatedByString:@" "].count;

Apple Docs mengatakan:

Biasanya, teks label digambar dengan font yang Anda tentukan di properti font. Jika properti ini disetel ke YES, namun, dan teks dalam properti teks melebihi persegi panjang pembatas label, penerima mulai mengurangi ukuran font hingga string pas atau ukuran font minimum tercapai. Di iOS 6 dan versi lebih lama, properti ini hanya efektif jika properti numberOfLines disetel ke 1.

Tapi ini bohong. Sebuah kebohongan yang kuberitahukan padamu! Itu benar untuk semua versi iOS. Secara khusus, ini berlaku saat menggunakan a UILabeldalam UICollectionViewCellyang ukurannya ditentukan oleh batasan yang disesuaikan secara dinamis pada waktu proses melalui tata letak khusus (mis.self.menuCollectionViewLayout.itemSize = size ).

Jadi, saat digunakan bersama dengan adjustsFontSizeToFitWidthdan minimumScaleFactor, seperti yang disebutkan dalam jawaban sebelumnya, pengaturan secara terprogram numberOfLinesberdasarkan jumlah kata memecahkan masalah tautan otomatis. Melakukan sesuatu yang serupa berdasarkan jumlah kata atau bahkan jumlah karakter mungkin menghasilkan solusi yang "cukup dekat".

Justin Whitney
sumber
0

Di Swift 4 (Secara terprogram):

let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200.0, height: 200.0))
label.adjustsFontSizeToFitWidth = true
label.numberOfLines = 0

label.text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."

view.addSubview(label)
Hadži Lazar Pešić
sumber
0

Swift 4, Xcode 9.4.1

Solusi yang berhasil untuk saya: Saya memiliki label dalam sel tampilan koleksi , dan teks label sedang dipangkas. Atur atribut seperti di bawah ini di Papan Cerita

Lines = 0
LineBreak = Word Wrap
Set yourlabel's leading and trailing constraint = 0 (using Autolayout)
Naishta
sumber