Soru Metni bir UILabel içinde dikey olarak hizala


Benim bir UILabel iki satırlık metin alanıyla. Bazen metin çok kısa olduğunda, bu metin etiketin dikey merkezinde görüntülenir.

Metni her zaman en üstte olacak şekilde dikey olarak nasıl hizalarım? UILabel?

image representing a UILabel with vertically-centered text


1986
2018-06-28 08:54


Menşei




Cevaplar:


Düşey hizalamayı ayarlamanın bir yolu yoktur. UILabelancak etiketin çerçevesini değiştirerek aynı etkiyi elde edebilirsiniz. Etiketlerimi turuncu yaptım, böylece neler olduğunu net bir şekilde görebilesiniz.

İşte bunu yapmanın hızlı ve kolay yolu:

    [myLabel sizeToFit];

sizeToFit to squeeze a label


Birden fazla satır yapacak uzun metne sahip bir etiketiniz varsa, numberOfLines için 0 (sıfır burada sınırsız sayıda satır anlamına gelir).

    myLabel.numberOfLines = 0;
    [myLabel sizeToFit];

Longer label text with sizeToFit


Daha uzun versiyon

Etiketimi kod haline getireceğim, böylece neler olduğunu görebileceksiniz. Bunun çoğunu Interface Builder'da da kurabilirsiniz. Kurulumum, kenar boşluklarını (20 puan) göstermek için Photoshop'ta yaptığım bir arka plan resmiyle View Based Uygulamasıdır. Etiket çekici bir turuncu renktedir, böylece boyutlarda neler olduğunu görebilirsiniz.

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 20 point top and left margin. Sized to leave 20 pt at right.
    CGRect labelFrame = CGRectMake(20, 20, 280, 150);
    UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
    [myLabel setBackgroundColor:[UIColor orangeColor]];

    NSString *labelText = @"I am the very model of a modern Major-General, I've information vegetable, animal, and mineral";
    [myLabel setText:labelText];

    // Tell the label to use an unlimited number of lines
    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

    [self.view addSubview:myLabel];
}

Kullanmanın bazı kısıtlamaları sizeToFit orta veya sağa hizalı metin ile oynamak. İşte olan:

    // myLabel.textAlignment = NSTextAlignmentRight;
    myLabel.textAlignment = NSTextAlignmentCenter;

    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

enter image description here

Etiket hala sabit bir sol üst köşeye sahip. Orijinal etiketin genişliğini bir değişkene kaydedebilir ve ardından ayarlayabilirsiniz. sizeToFitveya bu sorunlara karşı koymak için sabit bir genişlik verin:

    myLabel.textAlignment = NSTextAlignmentCenter;

    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

    CGRect myFrame = myLabel.frame;
    // Resize the frame's width to 280 (320 - margins)
    // width could also be myOriginalLabelFrame.size.width
    myFrame = CGRectMake(myFrame.origin.x, myFrame.origin.y, 280, myFrame.size.height);
    myLabel.frame = myFrame;

label alignment


Bunu not et sizeToFit İlk etiketinizin minimum genişliğine saygı gösterecektir. Eğer geniş bir etiketle başlarsanız sizeToFit Üzerinde, 100 (veya biraz daha az) genişliğe sahip bir (muhtemelen çok uzun) bir etiket verir. Etiketinizi yeniden boyutlandırmadan önce istediğiniz minimum genişliğe ayarlamak isteyebilirsiniz.

Correct label alignment by resizing the frame width

Dikkat edilmesi gereken diğer şeyler:

olup olmadığını lineBreakMode saygı duyulur nasıl ayarlandığına bağlıdır. NSLineBreakByTruncatingTail (varsayılan) sonra yoksayılır sizeToFitDiğer iki kesme modu (baş ve orta) gibi. NSLineBreakByClipping ayrıca göz ardı edilir. NSLineBreakByCharWrapping her zamanki gibi çalışır. Çerçeve genişliği hala en sağdaki harfe uyacak şekilde daralır.


Mark Amery Yorumlar'da Otomatik Düzen'i kullanarak NIB'ler ve Storyboard'lar için bir düzeltme verdi:

Etiketiniz bir alt göstergenin alt öğesi olarak bir etiket veya hikaye tahtasına dahil edilmişse view autolayout kullanan bir ViewController sizeToFit çağırmak viewDidLoad çalışmaz, çünkü autolayout boyutları ve sonra alt gösterimleri yerleştirir viewDidLoad çağrılır ve hemen etkilerini geri alır sizeToFit aramak. Ancak, arama sizeToFit içinden viewDidLayoutSubviews  irade iş.


Orijinal Cevabım (posterity / referans için):

Bu kullanır NSString yöntem sizeWithFont:constrainedToSize:lineBreakMode: Bir dizgiye sığdırmak için gereken çerçeve yüksekliğini hesaplamak için, orijini ve genişliği ayarlar.

Eklemek istediğiniz metni kullanarak etiketin çerçevesini yeniden boyutlandırın. Böylelikle herhangi bir sayıda çizgi alabilirsin.

CGSize maximumSize = CGSizeMake(300, 9999);
NSString *dateString = @"The date today is January 1st, 1999";
UIFont *dateFont = [UIFont fontWithName:@"Helvetica" size:14];
CGSize dateStringSize = [dateString sizeWithFont:dateFont 
        constrainedToSize:maximumSize 
        lineBreakMode:self.dateLabel.lineBreakMode];

CGRect dateFrame = CGRectMake(10, 10, 300, dateStringSize.height);

self.dateLabel.frame = dateFrame;

2563
2018-06-28 10:36



autolayout'u kaldırmanız gerekiyor - hungbm06
Sorunu çözmek için basit bir yol: stackoverflow.com/a/26632490/636559 - AboulEinein
Otomatik düzen ve film şeridini kullanırsanız, "Oluşturma zamanında kaldır" seçeneği ile bir kısıtlama eklemeye yardımcı olur - JK ABC
Bununla çalışırken buna ihtiyacınız varsa adjustsFontSizeToFitWidth daha sonra sizeToFit öğesini kullanın ve etiketin çerçevesini 0, 0, theWidthYouWant, label.frame.size.height olarak ayarlayın (size, sizeToFit tarafından belirlenen yeni yükseklik). adjustsFontSizeToFitWidth - Albert Renshaw
Bu cevap gereksiz bir şekilde karmaşıktır ve bir "kelime" kelimesini kullanır. Aşağıda, dikey içeriği kucaklamanın önceliğini değiştirmek için aşağıdaki öneriye bakın. Herhangi bir kod gerektirmez ... - beetree


  1. Yeni metni ayarla:

    myLabel.text = @"Some Text"
    
  2. Yı kur maximum number satır 0 (otomatik):

    myLabel.numberOfLines = 0
    
  3. Etiketin çerçevesini maksimum boyuta ayarlayın:

    myLabel.frame = CGRectMake(20,20,200,800)
    
  4. Aramak sizeToFit İçeriğin sığması için çerçeve boyutunu küçültmek:

    [myLabel sizeToFit]
    

Etiket çerçevesi artık metninize uyacak kadar yüksek ve geniş. Sol üst kısım değiştirilmemelidir. Bunu sadece sol üstte hizalanmış metinle test ettim. Diğer hizalamalar için, çerçeveyi daha sonra değiştirmeniz gerekebilir.

Ayrıca, etiketimin kelime kaydırma özelliği etkin.


315
2017-08-27 16:24



Hey Ben, eski koduma tekrar baktım ve cevabımı gerekli adımlarla güncelledim. - Jakob Egger
Bu benim için iyi çalıştı. UILabel'imin boyutlarını ayarladı ve numberOfLines'i değiştirdikten sonra IB'de 0'a ayarladıktan sonra [myLabel sizeToFit] adlı metni ayarladıktan sonra. - Dan Ellis
Attr'deki satır sayısını ayarladıktan sonra benim için mükemmel çalışıyor. Müfettiş - d2burke
1'den fazla hat sayısı durumunda çalışmaz - Tom
İki satırlık bir etiket istediğinizde işe yaramıyor, ancak metin daha fazla satır gerektiriyor. - Jose Manuel Abarca Rodríguez


Uzantı çözümüne başvurularak:

for(int i=1; i< newLinesToPad; i++) 
    self.text = [self.text stringByAppendingString:@"\n"];

ile değiştirilmelidir

for(int i=0; i<newLinesToPad; i++)
    self.text = [self.text stringByAppendingString:@"\n "];

Eklenen her yeni satırda ek alan gerekir çünkü iPhone UILabels'sondaki vagon dönüşleri göz ardı ediliyor gibi görünüyor :(

Benzer şekilde, alignBottom da bir @" \n@%" yerine "\n@%" (döngü başlatması için "(int i = 0 ..." için de) ile değiştirilmelidir.

Aşağıdaki uzantı benim için çalışıyor:

// -- file: UILabel+VerticalAlign.h
#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end

// -- file: UILabel+VerticalAlign.m
@implementation UILabel (VerticalAlign)
- (void)alignTop {
    CGSize fontSize = [self.text sizeWithFont:self.font];
    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label
    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;
    for(int i=0; i<newLinesToPad; i++)
        self.text = [self.text stringByAppendingString:@"\n "];
}

- (void)alignBottom {
    CGSize fontSize = [self.text sizeWithFont:self.font];
    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label
    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;
    for(int i=0; i<newLinesToPad; i++)
        self.text = [NSString stringWithFormat:@" \n%@",self.text];
}
@end

Sonra ara [yourLabel alignTop]; veya [yourLabel alignBottom]; her bir metin mesajından sonra.


151
2017-09-09 13:01



@ D.S. Eklediğini fark ettim VerticalAlign sonra parantez arasında @implementation UILabel. Objective-C'ye yeni olmak Daha önce bu sözdizimine rastlamamıştım. Bu ne denir? - Julian
İnanılmaz, kategoriler hakkında bilmiyordum, bu bana Objective-c dili için daha fazla değer veriyor. Daha fazla dil öğrenmek, iyi bir programcı olmak için çok önemlidir. - JeroenEijkhof
Bir oy verdi. ama iirc bu bir dezavantajı olan satır sayısını bilmiyorsanız işe yaramaz - Tjirp
3 satır metin gösterip metni metne hizalamam gerekiyor. Yani, 3'e doğru satır sayısı belirledim. Bunu 3 olarak ayarladığımda, metnin daha az olması durumunda “...” görüyorum (bu, bir satıra sığar). Bundan kaçınmak için "..." - Satyam
2'ye ayarlı satırlarım var ancak alignTop veya alignBottom için eksik olan bir şey farketmiyor mu? label = [[UILabel alloc] init]; label.numberOfLines = 2; label.frame = CGRectMake (0, TABS_HEIGHT-25, self.frame.size.width, 25); label.font = [UIFont fontWithName: @ "Arial" size: 10]; label.textAlignment = UITextAlignmentCenter; [label alignTop]; - htafoya


Sadece kimseye herhangi bir yardımın olması durumunda, aynı problemi yaşadım, ancak sorunu yalnızca kullanarak değiştirerek sorunu çözebildim. UILabel kullanmak UITextView. Bunun herkes için geçerli olmadığını takdir ediyorum çünkü işlevsellik biraz farklı.

Kullanmaya geçerseniz UITextViewKaydırma Görünümü özelliklerinin yanı sıra Kullanıcı Etkileşimi Etkinleştir seçeneğini de kapatabilirsiniz ... Bu, bir etikete daha çok benzemeye zorlayacaktır.

enter image description here


126
2017-10-05 12:46



Birçok UILabel'in metin görünümlerine dönüştürülmesi durumunda bunun performansı nasıl etkileyeceğinden emin değilsiniz. - ninjaneer
Bu konudaki tüm diğer çözümler iOS 7'de benim için çalışmadı (her ne sebeple olursa olsun). Ama sadece bir UITextView Bana hemen istenen sonucu verdi. - Clifton Labrum
Bu bir geçici çözüm, otantik görünmesini sağlamak için hala bazı ayarlamalar gerekiyor, ama gerçekten bu gördüğüm en kolay hiçbir kod çözümü, başparmak yukarı. - Itai Spector
Bu çözümü beğendim. Görüldüğü gibi, göreceli olarak basit bir görünümde basit bir etiket için performans sorunları olabilir ve bu, ihtiyaç duyduğum şey için mükemmeldi (ve herhangi bir performans etkisini göremiyorum). - JCutting8
Bu yöntemin küçük bir dezavantajı, metne ekstra iç dolgu getirecek olmasıdır. Hızlı bir düzeltme, olumsuz bir kısıtlama getirmektir. - Sira Lam


Kafma yok, yaygara yok

@interface MFTopAlignedLabel : UILabel

@end


@implementation MFTopAlignedLabel

- (void)drawTextInRect:(CGRect) rect
{
    NSAttributedString *attributedText = [[NSAttributedString alloc]     initWithString:self.text attributes:@{NSFontAttributeName:self.font}];
    rect.size.height = [attributedText boundingRectWithSize:rect.size
                                            options:NSStringDrawingUsesLineFragmentOrigin
                                            context:nil].size.height;
    if (self.numberOfLines != 0) {
        rect.size.height = MIN(rect.size.height, self.numberOfLines * self.font.lineHeight);
    }
    [super drawTextInRect:rect];
}

@end

Ateş yok, Nesne-c yok, yaygara yok ama Swift 3:

class VerticalTopAlignLabel: UILabel {

    override func drawText(in rect:CGRect) {
        guard let labelText = text else {  return super.drawText(in: rect) }

        let attributedText = NSAttributedString(string: labelText, attributes: [NSFontAttributeName: font])
        var newRect = rect
        newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height

        if numberOfLines != 0 {
            newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
        }

        super.drawText(in: newRect)
    }

}

80
2018-05-21 07:47



Hızlı versiyonu benim için herhangi bir yan etkisi olmadan çalıştı! Harika iş! - l.vasilev
Muhtemelen en iyi cevap, tüm senaryolarda çalışır. label UITableviewCell içinde ise sizeToFit çalışmaz. İyi iş. - rajat chauhan
Harika adam çalışıyor - anoop4real


Yukarıdaki cevap gibi, ama çok doğru değildi, ya da kod içine tokatlamak kolay değildi, bu yüzden biraz temizledim. Bu uzantıyı kendi .h ve .m dosyasına ekleyin veya yalnızca kullanmayı amaçladığınız uygulamanın üzerine yapıştırın:

#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end


@implementation UILabel (VerticalAlign)
- (void)alignTop
{
    CGSize fontSize = [self.text sizeWithFont:self.font];

    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label


    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];


    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

    for(int i=0; i<= newLinesToPad; i++)
    {
        self.text = [self.text stringByAppendingString:@" \n"];
    }
}

- (void)alignBottom
{
    CGSize fontSize = [self.text sizeWithFont:self.font];

    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label


    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];


    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

    for(int i=0; i< newLinesToPad; i++)
    {
        self.text = [NSString stringWithFormat:@" \n%@",self.text];
    }
}
@end

Daha sonra kullanmak için, metninizi etikete koyun ve ardından hizalamak için uygun yöntemi arayın:

[myLabel alignTop];

veya

[myLabel alignBottom];

76
2018-03-04 02:44



Bunun bir Swift 3 sürümünü eklemek isteyen var mı? - Duncan Groenewald


Bunu başarmak için daha hızlı (ve daha kirli) bir yol, UILabel'ın satır kesme modunu "Klip" olarak ayarlayarak ve sabit miktarda yeni satır ekleyerek gerçekleştirmektir.

myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];

Bu çözüm herkes için işe yaramaz - özellikle, dizenin sonunda gösterdiğiniz satır sayısını aşarsa "..." ifadesini göstermek istiyorsanız, aşağıdakilerden birini kullanmanız gerekir: kodun uzun bitleri - ama birçok durumda bu size ihtiyacınız olanı sağlar.


66
2018-04-18 21:08



Çizgi kırma modunun 'klip' ​​olarak ayarlanması, etiketin otomatik boyutlandırılmasını bozar. kullanım UILineBreakModeWordWrap yerine. - Niels van der Rest
ve daha iyi boşluklar ekleyin "\ n \ n" - djdance


Yerine UILabel kullanabilirsin UITextField dikey hizalama seçeneğine sahip olan:

textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction

56
2018-02-10 10:36



Uyarı: UITextField yalnızca tek bir metin satırına izin verir. - David James
@DavidJames yorumunu tamamlamak için: UITextView daha uygun olurdu - CedricSoubrie


Bununla uzun zamandır mücadele ettim ve çözümümü paylaşmak istedim.

Bu size bir UILabel metni 0,5 ölçeğe indirecek ve metni dikey olarak ortalayacak. Bu seçenekler Storyboard / IB'de de mevcuttur.

[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];

47
2017-10-16 16:38



Sağlanan tüm cevaplar arasında mükemmel çalıştı. Teşekkürler @David Greco. Bu özelliklerin yanı sıra, FOSSizeToFitWidth öğesini YES olarak ayarlarsak, metin etiketin çerçevesini değiştirmeden çerçeveye sığar. - Ashok Kumar S
Detaylandırır mısın? Sözdizimini almadım ve aynı zamanda storyboard ui oluşturucuda da nasıl ayarlayabiliriz? - Sasuke Uchiha