UILabel, metni etiket boyutuna sığacak şekilde otomatik olarak küçülmüyor


119

Bu tuhaf sorunum var ve şu anda 8 saatten fazla bir süredir bununla uğraşıyorum .. Duruma bağlı olarak UILabelsboyutu dinamik olarak hesaplamam gerekiyor ,
örneğin
benim UIViewControllerbir olay alıyor ve UILabelsboyutunu değiştiriyorum . büyükten küçüğe. Benim UILabelboyutum küçülüyor ve gereken doğru boyutu alıyorum, ancak metin UILabelaynı kalıyor, aynı yazı tipi boyutu vb. Tüm metnin sığması için yazı tipinin küçülmesine ihtiyacım var UILabel. Öyleyse soru, metnin etiketime uyması autoshrinkingveya bunun gibi bir şeyin nasıl yapılacağıdır?

Benim içinde xib, UILabels autoshrinkaynı zamanda, kontrol edilir çizgilerin sayısı 0 olarak ayarlanır ve aynı zamanda benim dize yeni hat sembolleri (\ n) vardır ve ben seçtiğiniz linebreakmode için wordwrap. Belki birisi benim şu anki durumdaydı ve bana yardım edebilir mi? Gerçekten minnettar olurum.

Şimdiden teşekkürler!

DÜZENLEME: UILabel minimum yazı tipi boyutu 10 olarak ayarlandı


Ayarladığınız etiket için yazı tipinizin minimum boyutu nedir lütfen ekleyin.
AJPatel

Yanıtlar:


160

Hala daha iyi bir çözüm arıyorsanız, bence istediğiniz bu:

Başlık dizesini etiketin sınırlayıcı dikdörtgenine sığdırmak için yazı tipi boyutunun küçültülmesi gerekip gerekmediğini belirten bir Boolean değeri (bu özellik yalnızca numberOfLinesözellik 1 olarak ayarlandığında etkilidir ).

Bu özelliği ayarlarken, minimumScaleFactorAYARLANMALIDIR (iyi bir varsayılan 0,5'tir).

hızlı

var adjustsFontSizeToFitWidth: Bool { get set }

Objective-C

@property(nonatomic) BOOL adjustsFontSizeToFitWidth;

Harfler arasındaki boşluğun dizeyi etiketin sınır dikdörtgenine sığacak şekilde ayarlanması gerekip gerekmediğini gösteren Boolean değeri.

hızlı

var allowsDefaultTighteningForTruncation: Bool { get set }

Objective-C

@property(nonatomic) BOOL allowsDefaultTighteningForTruncation;

Kaynak .


18
Ek olarak, minimumFontSizeiOS 6.0'da kullanımdan kaldırılmıştır. minimumScaleFactorBunun yerine kullanın .
lester

14
Evet otomatik küçültme, UILabel'de birden çok satır için çalışmaz. Bunu hayal etmeye çalışın: çok satırlı bir metniniz var, onu genişliğe "sığacak" şekilde küçültmek istiyorsunuz. Öyleyse, tüm metni tek bir satıra sığacak şekilde küçültmeli mi yoksa kelimeler aynı satırda kalmalı ve her genişliğe sığacak şekilde küçülmeli mi? İkincisi en yaygın durumdur, ancak kelimelerin kendilerini birden çok satırda düzenlemek için ayarlandığını unutmayın. Metnin otomatik düzenlemesi devre dışı bırakılsa bile, her kelime genişliğe sığmayacağından, farklı yazı tipi boyutuna sahip metnin her satırıyla yüzleşmeniz gerekecektir.
lester

2
Buradaki Kategori ile bu cevabın oldukça iyi olduğunu düşünüyorum, yine de uyguladığınız şey olabilir. Bu kesinlikle Apple API'de eksik olan bir şeydir veya belki de küçülmenin birden çok satırlık statik metin için yaygın bir kullanım durumu olması gerektiğini görmüyorlar .
lester

1
evet, bu iyi bir nokta, ama yine de, eğer satır sayısını 0 olarak ayarlarsam, bu bir veya daha fazla satır olabileceğine dair net bir ifade olur. Ve otomatik küçültme, sanırım satır numaralarıyla caydırıcı olabilir .. Ama yine de, her şeyi açıklığa kavuşturduğunuz için teşekkürler. Yanlış bir şey yaptığımı sanıyordum. Kategori iyi bir fikir, sanırım bunu ihtiyacım olan başka bir projede yapacağım. Yardımınız için minnettarız, iyi şanslar;)
Lukas

4
@lester Mevcut boyutları verildiğinde etiket için bildirilen satır sayısında metnin tamamı görünecek şekilde küçülmelidir. Her satırı farklı bir boyut yapmaya çalışmasına gerek yoktur. Bunu çözememesine gerçekten şaşırdım. Öyleyse görüntülenecek (potansiyel olarak) uzun bir dizem varsa , ya birden çok satırım olabilir ya da otomatik boyutlandırabilirim, ikisini birden değil. Bu çok şirin.
devios1

125

AutoshrinkIOS 9.2, Xcode 7.2'de UILabel çalışmasını bu şekilde elde ediyorum (özellikle 6s Plus Storyboard'dan 4s cihazında etiket yazı tipi uydurma yüksekliği için) ...

görüntü açıklamasını buraya girin

  • Satır sayısı 0
  • Satır Kesmeleri: Klip
  • Otomatik daraltma: Minimum Yazı Tipi Ölçeği 0,25

15
Bunlar, bir etiketin gerçekten küçülmesi için gereken 3 bileşen, klip satırı sonu ayarını kaçırıyordum. Ayrıca, diğer etiketlere bitişikse (bu da otomatik olarak daralabilir), o zaman sıkıştırma / sarma önceliklerinin ayarlanması veya açık genişlik veya yükseklik kısıtlamalarının verilmesi gerekir. Bu şu anda kabul edilen cevap olmalıdır.
Korey Hinton

3
Satır sayısı benim için yaptı! Teşekkür ederim
Michael

Etiketinizin özellikle başta ve sonda olmak üzere tüm kısıtlamalara sahip olduğundan emin olun.
Mashhadi

2
Xcode8'de aynı seçenekleri denedim ve çalışmadığını buldum. Bu konuda fikri olan varsa lütfen bana yardım et.
Ganesh

75

minimumFontSize iOS 6'da kullanımdan kaldırılmıştır.

Bunun minimumScaleFactoryerine kullanın minmimumFontSize.

lbl.adjustsFontSizeToFitWidth = YES
lbl.minimumScaleFactor = 0.5

Swift 5

lbl.adjustsFontSizeToFitWidth = true
lbl.minimumScaleFactor = 0.5

İyi cevapladı. Sorunumu çözdüm. Teşekkürler
Abdul Yasin

1
@AntonMatosov, hayır, öyle değil!
Iulian Onofrei

2
Evet, (şimdi) - satır sonlarını Kelime Kaydırma yerine Kuyruğu
Kes olarak

21

benim çözümüm de boole etiketi.adjustsFontSizeToFitWidth = YES; FAKAT. Builder arayüzünde Kelime Sarma anahtarını " CLIP " konumuna getirmelisiniz . Ardından Etiketleri otomatik olarak küçültün. Bu çok önemli.


3
Yalnızca "Sözcük Kaydırma" dan "Klip" e değiştirdiğimde Otomatik Küçültme benim için işe yaradı.
NicJ

Kelime kaydırmayı klip olarak değiştirdiğimde, aslında sıfır satırlı bir etikette yeniden boyutlandırmayı başardım. Tanrım, bu belgelenirse iyi olurdu.
BelirlenmişNerd

12

Swift 3'te (Programlı Olarak) Bunu yapmam gerekiyordu:

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

5

Gibi yazabilirsin

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];

Bu şekilde satır sayısını hesaplayabilirsiniz

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";

Umarım bu size yardımcı olur :-) cevabınızı bekliyorum


yani satır sayısını etiketime ayarlarsanız metin otomatik olarak daralır mı?
Lukas

içeriğinizin genişliği yoksa bir
sonraki satırı

Hey önerdiğin gibi yaptım ama işe yaramıyor, neden satır sayısı bana yardımcı olsun?
Lukas

haklısın işe yaramaz denedim ama senin için bir çözüm buldum bir sonraki cevabım
Birju

lbl.adjustsFontSizeToFitWidth = EVET; Benim için çalıştı!
Geliştirici

4

Sonunda cevabımı bulamadım. Ve bence otomatik küçültme birden çok satırda çalışmıyor. Bu bağlantıdaki öneriyi kullandım: birden çok satıra sahip bir UILabel üzerinde otomatik küçült

Çözümler, belirli bir genişlikte metin yüksekliğini hesaplamak ve metin daha büyükse, yazı tipi boyutunu küçültmek ve ardından yükseklik ihtiyacınız olan boyuta eşit veya daha az olana kadar aynı işlemi tekrar yapmaktır.

Bunun neden uygulanmasının bu kadar zor olduğunu anlamıyorum. Bir şeyi kaçırırsam, herkes beni düzeltebilir :)


Buradaki diğer yanıtlarda olduğu gibi, eksik olan anahtar kelime Kaydırmayı "Klip" olarak ayarlamanız gerektiğiydi. Sezgisel değildir, ancak bu, istediğiniz şekilde otomatik olarak küçültmek için bir UILabel almak için gereklidir. Bu, çok satırlı bir UILabel ile çalışır.
Duncan Babbage

4

Bu, Xcode 8.2.1 (8C1002) çalıştıran Swift 3 içindir

Bulduğum en iyi çözüm, Storyboard veya IB'de etikete sabit bir genişlik ayarlamaktır. Kısıtlamalarınızı kenar boşluklarıyla sınırlayın. ViewDidLoad'a aşağıdaki kod satırlarını ekleyin:

override func viewDidLoad() {
            super.viewDidLoad()

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

kenar boşluğuna etiket kısıtlamaları

kenar boşluğuna sabit genişlikte etiket kısıtlamaları

nitelik müfettişi

Bu bir cazibe gibi çalıştı ve yeni bir satıra taşmaz ve metni herhangi bir tuhaf sorun olmadan etiketin genişliğine sığacak şekilde küçültür ve Swift 3'te çalışır.


4

Bu harika bir soru, çünkü UIKitşimdiye kadar yerleşik işlevselliğin veya ilgili bir çerçevenin parçası olacakmış gibi geliyor . İşte sorunun güzel bir görsel örneği:

Animasyonu yeniden boyutlandırma yazı tipi

Etrafında kolay bir yol yok, ama kesinlikle mümkün. Bunu yapmanın bir yolu, görünümün sınırlarına makul ölçüde yakın bir tane bulana kadar farklı yazı tipi boyutlarını programlı olarak denemektir. Bunu veya boundingRect()işleviyle gerçekleştirebilirsiniz . Örneğin:NSStringNSAttributedString

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

Tam bir kaba kuvvet yaklaşımından daha verimli olmak için ikili arama yapabilirsiniz. Gerçekten sağlam bir şey arıyorsanız, doğru kelime kaydırma ve iOS yazı tipi önbelleğe alma performansı dahil olmak üzere biraz daha ilgili bazı hususlar da vardır.

Ekrandaki metni sadece kolay bir şekilde göstermeyi önemsiyorsanız, Swift'de bir üretim uygulamasında da kullandığım sağlam bir uygulama geliştirdim. UIViewBirden çok satır dahil herhangi bir girdi metni için verimli, otomatik yazı tipi ölçeklendirmeye sahip bir alt sınıftır. Kullanmak için basitçe şöyle bir şey yaparsınız:

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

Bu kadar! Tam kaynağı burada bulabilirsiniz: https://github.com/FlickType/AccessibilityKit

Bu yardımcı olur umarım!


1
Kasım 2018: FlickType ve AccessibilityKit'in gizli olduğu veya kaldırıldığı görünür.
Chris Paveglio

3

İOS 9'da şunları yapmam gerekiyordu:

  1. Etiketin solundan ve sağından denetime kısıtlamalar ekleyin.
  2. Satır kesme modunu IB'de kırpmaya ayarlayın.
  3. IB'de satır sayısını 1'e ayarlayın.

Birisi satır sayısını 0 olarak ayarlamayı önerdi, ancak benim için bu sadece etiketin birden fazla satıra gitmesini sağladı ...


Bu benim için hile yaptı. Statik bir hücrede a UILabelve a seçtim UITextFieldve "Otomatik Yerleşim Sorunlarını Çöz" ve "Eksik Kısıtlamaları Ekle" ye tıkladım. Her şey hizalandı, ancak Autoshrink'in etikete olan mesafeyi bilmesi gerekiyordu, "Eksik Kısıtlamaları Ekle" için bir kısıtlama eklemedi.
Adrian

2

Başlangıç ​​Etiketini tahsis ettikten sonra aşağıdaki kodu yazabileceğinizi düşünüyorum.

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];

Benimle çalışıyor gayet iyi Kullan onu


1
teşekkürler, ancak bu yazı tipini hesaplamayacak veya anladığım kadarıyla minimuma indirmeyecek ve ayrıca minimum yazı tipiniz neden normalden daha büyük?
Lukas

2

İki yıl geçti ve bu konu hala etrafta ...

İOS 8 / XCode 6.1'de, bazen benim UILabel( UITableViewCella'da oluşturulmuş , AutoLayout açıkken ve esnek kısıtlamalar, böylece bol miktarda alan vardı) metin dizesine sığacak şekilde kendini yeniden boyutlandırmayacağını fark ediyordum.

Çözüm, önceki yıllarda olduğu gibi, metni ayarlamak ve ardından aramaktı sizeToFit.

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

(İç çekmek.)


1

Bunu nasıl yapacağınız aşağıda açıklanmıştır: İstediğiniz etkiyi elde etmek istediğiniz etiketin aşağıdaki mesaj etiketi olduğunu varsayalım. Şimdi, şu basit kod satırını deneyin:

    //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.

Cevabınız için teşekkürler, ancak etiketin yüksekliğini hesaplamama gerek yok, sabit boyutum var ve buna bağlı olarak yazı tipimin gerekirse küçülmesi gerekiyor.
Lukas

1

numberOfLines > 1 Yaptığım şey böyle bir koşul yaptıysa işe yaramıyor

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

0

Partiye geç gelmekle birlikte, her satırda bir kelime kullanma ek zorunluluğum olduğundan, bu ekleme benim için hile yaptı:

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

Apple Docs diyor ki:

Normalde etiket metni, font özelliğinde belirttiğiniz fontla çizilir. Ancak bu özellik EVET olarak ayarlanırsa ve metin özelliğindeki metin etiketin sınırlayıcı dikdörtgenini aşarsa, alıcı, dize sığana veya minimum yazı tipi boyutuna ulaşılana kadar yazı tipi boyutunu küçültmeye başlar. İOS 6 ve önceki sürümlerde, bu özellik yalnızca numberOfLines özelliği 1 olarak ayarlandığında etkilidir.

Ama bu bir yalan. Sana söylediğim bir yalan! Tüm iOS sürümleri için geçerlidir. Özellikle, boyutun çalışma zamanında özel düzen (örn. ) Aracılığıyla dinamik olarak ayarlanan kısıtlamalar tarafından belirlendiği bir UILabeliçinde kullanıldığında bu doğrudur .UICollectionViewCellself.menuCollectionViewLayout.itemSize = size

İle birlikte kullanıldığında Yani adjustsFontSizeToFitWidthve minimumScaleFactorprogramlı ayar, önceki cevaplar belirtildiği gibi, numberOfLineskelime sayısının dayalı autoshrink sorunu çözdü. Kelime sayısına veya hatta karakter sayısına bağlı olarak benzer bir şey yapmak "yeterince yakın" bir çözüm üretebilir.


0

Swift 4'te (Programlı):

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)

0

Swift 4, Xcode 9.4.1

Benim için işe yarayan çözüm: Koleksiyon görüntüleme hücresinde bir etiketim vardı ve etiket metni kırpılıyordu. Öznitelikleri Storyboard'da aşağıdaki gibi ayarlayın

Lines = 0
LineBreak = Word Wrap
Set yourlabel's leading and trailing constraint = 0 (using Autolayout)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.