Yanıtlar:
A üzerinde dikey hizalamayı ayarlamanın bir yolu yoktur UILabel
, ancak etiketin çerçevesini değiştirerek aynı efekti elde edebilirsiniz. Neler olduğunu net bir şekilde görebilmeniz için etiketlerimi turuncu yaptım.
İşte bunu yapmanın hızlı ve kolay yolu:
[myLabel sizeToFit];
Birden fazla satır, set yapacak daha uzun metin ile bir etiketi varsa numberOfLines
için 0
(sıfır burada çizgilerin sınırsız sayıda anlamına gelir).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Daha Uzun Versiyon
Neler olup bittiğini görebilmek için etiketimi kodda yapacağım. Bunların çoğunu Arayüz Oluşturucu'da da ayarlayabilirsiniz. Kurulumum, kenar boşluklarını göstermek için Photoshop'ta yaptığım arka plan görüntüsüne sahip Görünüm Tabanlı bir Uygulama (20 puan). 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];
}
Bazı kullanım kısıtlamaları sizeToFit
orta veya sağa hizalanmış metinle devreye girer. İşte olanlar:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
Etiket hala sabit bir sol üst köşeyle boyutlandırılmıştır. Orijinal etiketin genişliğini bir değişkene kaydedip daha sonra ayarlayabilirsiniz sizeToFit
veya bu sorunlara karşı koymak için sabit bir genişlik verebilirsiniz:
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;
Not sizeToFit
İlk etiketin asgari genişliğini saygı duyacağım. 100 genişliğinde bir etiketle başlarsanız ve sizeToFit
onu çağırırsanız , size 100 (veya biraz daha az) genişlikte (muhtemelen çok uzun) bir etiket verir. Yeniden boyutlandırmadan önce etiketinizi istediğiniz minimum genişliğe ayarlamak isteyebilirsiniz.
Dikkat edilmesi gereken başka şeyler:
Uyulup lineBreakMode
uyulmadığı, nasıl ayarlandığına bağlıdır. NSLineBreakByTruncatingTail
(varsayılan) sizeToFit
ve diğer iki kesme modu (baş ve orta) sonra dikkate alınmaz . NSLineBreakByClipping
de yok sayılır. NSLineBreakByCharWrapping
her zamanki gibi çalışır. Çerçeve genişliği hala en sağdaki harfe sığacak şekilde daraltılmıştır.
Mark Amery , yorumlarda Otomatik Mizanpaj kullanan NIB'ler ve Storyboard'lar için bir düzeltme verdi:
Etiketiniz, otomatik yerleşim
view
kullanan bir ViewController öğesinin alt görünümü olarak bir uç veya film şeridinesizeToFit
dahilviewDidLoad
edilirse, otomatik yerleşim, alt görünümleri arandıktan sonra boyutlandırır ve konumlandırdığından aramanızı koymak işe yaramazviewDidLoad
.sizeToFit
aramak. Ancak çağıraraksizeToFit
içindenviewDidLayoutSubviews
irade çalışmaları.
Bu, bir dizeye sığdırmak için gereken kare yüksekliğini hesaplamak için NSString
yöntemi kullanır sizeWithFont:constrainedToSize:lineBreakMode:
, ardından başlangıç noktasını ve genişliği ayarlar.
Eklemek istediğiniz metni kullanarak etiketin çerçevesini yeniden boyutlandırın. Bu şekilde istediğiniz sayıda çizgiyi barındırabilirsiniz.
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;
adjustsFontSizeToFitWidth
sizeToFit kullanın ve ardından etiketin çerçevesini 0, 0 olarak ayarlayın, WididYouWant, label.frame.size.height (sizeToFit tarafından belirlenen yeni yüksekliktir) SONRA geçerlidiradjustsFontSizeToFitWidth
Yeni metni ayarlayın:
myLabel.text = @"Some Text"
Set maximum number
(otomatik) 0 hatları:
myLabel.numberOfLines = 0
Etiketin çerçevesini maksimum boyuta ayarlayın:
myLabel.frame = CGRectMake(20,20,200,800)
Çağrı sizeToFit
içeriği sadece uyacak şekilde kare boyutunu azaltmak için:
[myLabel sizeToFit]
Etiketler çerçevesi artık metninize sığacak kadar yüksek ve geniş. Sol üst kısım değiştirilmemelidir. Bunu sadece sola hizalanmış metinle test ettim. Diğer hizalamalar için daha sonra çerçeveyi değiştirmeniz gerekebilir.
Ayrıca, etiketimde sözcük kaydırma özelliği etkin.
Genişletme çözümüne bakıldığında:
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'un UILabels
sondaki satırbaşı geri döndürülüyormuş gibi görünüyor :(
Benzer şekilde, alignBottom @" \n@%"
yerine de ile güncellenmelidir "\n@%"
(döngü başlatma için "for (int i = 0 ..." ile de 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];
[yourLabel alignBottom];
her bir Etiket metin atamanızı veya sonra .
VerticalAlign
parantez arasına eklediğinizi fark ettim @implementation UILabel
. Objective-C için yeni olarak daha önce bu sözdizimi ile karşılaşmadım. Buna ne denir?
sizeWithFont:constrainedToSize:lineBreakMode:
ve sizeWithFont: iOS7'de her ikisi de amortismana tabi tutulur. Ayrıca, bu kategori yalnızca numberOfLines 0'dan büyük olduğunda etiketler üzerinde çalışır
Sadece kimseye herhangi bir yardım var bu durumda, ben de aynı problem vardı ama sadece kullanarak geçiş yaparak sorunu çözmeyi başardı UILabel
kullanmadan UITextView
. Bu, herkes için değil, çünkü işlevsellik biraz farklı olduğunu takdir ediyorum.
Kullanıma geçiş UITextView
yaparsanız, Kullanıcı Etkileşimi Etkin'in yanı sıra tüm Kaydırma Görünümü özelliklerini de kapatabilirsiniz ... Bu, onu daha çok etiket gibi davranmaya zorlar.
UITextView
bana hemen istenen sonucu verdi.
Karışıklık yok, karışıklık 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
Kargaşa yok, Objective-c yok, karışıklık 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)
}
}
Hızlı 4.2
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: [NSAttributedString.Key.font: 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)
}
}
Yukarıdaki cevap gibi, ama oldukça doğru değildi veya kod içine tokatlamak kolay değildi, bu yüzden biraz temizledim. Bu uzantıyı kendi .h ve .m dosyasına ekleyin veya kullanmak istediğiniz uygulamanın hemen üstüne 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
Ardından kullanmak için metninizi etikete yerleştirin ve ardından hizalamak için uygun yöntemi çağırın:
[myLabel alignTop];
veya
[myLabel alignBottom];
Bunu başarmanın daha hızlı (ve daha kirli) bir yolu, UILabel'in satır sonu modunu "Klip" olarak ayarlamak ve sabit miktarda yeni satır eklemektir.
myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];
Bu çözüm herkes için işe yaramaz - özellikle, dizenizin sonunda hala gösterdiğiniz satır sayısını aşarsa "..." göstermek istiyorsanız, aşağıdakilerden birini kullanmanız gerekir: daha uzun kod parçaları - ancak çoğu durumda bu size ihtiyacınız olanı alır.
UILineBreakModeWordWrap
Bunun yerine kullanın .
Storyboard'u kullanarak en kolay yaklaşım:
Göm Etiket içinde StackView Özellik Inspector'da StackView iki nitelikler aşağıdaki ve seti:
1- Axis
ilaHorizontal
,
2- Alignment
ilaTop
UILabel
Bazı UIView
alt sınıflara yerleştirmek ( UIView
genellikle yeterlidir) ve etiketin aşağı yönde büyümesine izin vermek için harika bir fikir . Teşekkürler!
UILabel
ve StackView işini yapsın. Teşekkürler!
Bunun yerine dikey hizalama seçeneğine sahip olanları UILabel
kullanabilirsiniz UITextField
:
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction
Uzun zamandır bununla mücadele ettim ve çözümümü paylaşmak istedim.
Bu, UILabel
metni 0,5 ölçeğe otomatik olarak çekecek ve metni dikey olarak ortalayacaktır. Bu seçenekler Storyboard / IB'de de mevcuttur.
[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
Yeni bir sınıf oluştur
LabelTopAlign
.h dosyası
#import <UIKit/UIKit.h>
@interface KwLabelTopAlign : UILabel {
}
@end
.m dosyası
#import "KwLabelTopAlign.h"
@implementation KwLabelTopAlign
- (void)drawTextInRect:(CGRect)rect {
int lineHeight = [@"IglL" sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, 9999.0f)].height;
if(rect.size.height >= lineHeight) {
int textHeight = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, rect.size.height)].height;
int yMax = textHeight;
if (self.numberOfLines > 0) {
yMax = MIN(lineHeight*self.numberOfLines, yMax);
}
[super drawTextInRect:CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, yMax)];
}
}
@end
İşte aynı şeyi yapan daha basit bir uygulama:
#import "KwLabelTopAlign.h"
@implementation KwLabelTopAlign
- (void)drawTextInRect:(CGRect)rect
{
CGFloat height = [self.text sizeWithFont:self.font
constrainedToSize:rect.size
lineBreakMode:self.lineBreakMode].height;
if (self.numberOfLines != 0) {
height = MIN(height, self.font.lineHeight * self.numberOfLines);
}
rect.size.height = MIN(rect.size.height, height);
[super drawTextInRect:rect];
}
@end
sizeToFit
Çözümlerden farklı olarak, daha kısa bir metni dinamik olarak daha uzun bir metinle değiştirseniz veya tam tersi olsa bile, aslında herhangi bir metni üste UILabel
koyar .
Arayüz Oluşturucu'da
UILabel
Mümkün olan en büyük Metnin boyutuna ayarlaLines
Özellik Denetçisinde '0' olarak ayarlayınKodunuzda
sizeToFit
Etiketinizi arayınKod Parçacığı:
self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
Uyarlanabilir kullanıcı arayüzü için (iOS8 veya sonrası), UILabel'ın Dikey Hizalaması, noOfLines
= 0` özellikleri değiştirilerek
StoryBoard'dan ve
Kısıtlamalar
UILabel LefMargin, RightMargin ve Üst Kenar Boşluğu Sınırlamalarını Ayarlama.
Değişiklik
Content Compression Resistance Priority For Vertical
= 1000` Böylece Dikey> Yatay.
Düzenlendi:
noOfLines=0
ve aşağıdaki kısıtlamalar istenen sonuçları elde etmek için yeterlidir.
Bir UILabel alt sınıfı oluşturun. Tıkır tıkır çalışıyor:
// TopLeftLabel.h
#import <Foundation/Foundation.h>
@interface TopLeftLabel : UILabel
{
}
@end
// TopLeftLabel.m
#import "TopLeftLabel.h"
@implementation TopLeftLabel
- (id)initWithFrame:(CGRect)frame
{
return [super initWithFrame:frame];
}
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{
CGRect textRect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
textRect.origin.y = bounds.origin.y;
return textRect;
}
-(void)drawTextInRect:(CGRect)requestedRect
{
CGRect actualRect = [self textRectForBounds:requestedRect limitedToNumberOfLines:self.numberOfLines];
[super drawTextInRect:actualRect];
}
@end
As tartışılan burada .
Bu amaca ulaşmak için bir fonksiyon yazdım. Bir göz atabilirsiniz:
// çok satırlı bir etiketin yüksekliğini dikey ile üste hizalanacak şekilde ayarlayın + (geçersiz) alignLabelWithTop: (UILabel *) label { CGSize maxSize = CGSizeMake (label.frame.size.width, 999); label.adjustsFontSizeToFitWidth = HAYIR; // gerçek yüksekliği al CGSize actualSize = [label.text sizeWithFont: label.font constrainedToSize: maxSize lineBreakMode: label.lineBreakMode]; CGRect rect = label.frame; rect.size.height = actualSize.height; label.frame = rect; }
.Nasıl kullanılır? (LblHello, Arayüz oluşturucu tarafından oluşturulduysa, bazı UILabel özniteliklerini atlarım)
lblHello.text = @ "Merhaba Dünya! Merhaba Dünya! Merhaba Dünya! Merhaba Dünya! Merhaba Dünya! Merhaba Dünya! Merhaba Dünya! Merhaba Dünya!"; lblHello.numberOfLines = 5; [Utils alignLabelWithTop: lblHello];
Blogumda da bir makale olarak yazdım: http://fstoke.me/blog/?p=2819
Tanıtılan sayfada kodun yanı sıra kodu okumak için biraz zaman aldım ve hepsinin etiketin kare boyutunu değiştirmeye çalıştıklarını, böylece varsayılan merkez dikey hizalamanın görünmeyeceğini gördüm.
Bununla birlikte, bazı durumlarda, etiketin çok fazla metni olsa bile etiketin tüm bu boşlukları işgal etmesini isteriz (örneğin, eşit yükseklikte birden çok satır).
Burada, etiketin sonuna sadece satır satırları pad ile çözmek için alternatif bir yol kullandım (pls aslında miras olduğunu unutmayın UILabel
, ancak gerekli değildir):
CGSize fontSize = [self.text sizeWithFont:self.font];
finalHeight = fontSize.height * self.numberOfLines;
finalWidth = 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 "];
}
Buradaki önerileri aldım ve bir UILabel'i saran ve boyutlandıracak ve satır sayısını üste hizalanacak şekilde ayarlayacak bir görünüm oluşturdum. Bir alt görünüm olarak bir UILabel yazın:
@interface TopAlignedLabelContainer : UIView
{
}
@end
@implementation TopAlignedLabelContainer
- (void)layoutSubviews
{
CGRect bounds = self.bounds;
for (UILabel *label in [self subviews])
{
if ([label isKindOfClass:[UILabel class]])
{
CGSize fontSize = [label.text sizeWithFont:label.font];
CGSize textSize = [label.text sizeWithFont:label.font
constrainedToSize:bounds.size
lineBreakMode:label.lineBreakMode];
label.numberOfLines = textSize.height / fontSize.height;
label.frame = CGRectMake(0, 0, textSize.width,
fontSize.height * label.numberOfLines);
}
}
}
@end
TTTAttributedLabel kullanabilirsiniz , dikey hizalamayı destekler.
@property (nonatomic) TTTAttributedLabel* label;
<...>
//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
Bu sorunun cevabının şimdi biraz güncel olmadığını buldum, bu yüzden bunu otomatik düzen hayranları için ekledik.
Otomatik düzen, bu sorunu oldukça önemsiz kılar. Etiketi eklediğimizi varsayarsak UIView *view
, aşağıdaki kod bunu başaracaktır:
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setText:@"Some text here"];
[label setTranslatesAutoresizingMaskIntoConstraints:NO];
[view addSubview:label];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[label]|" options:0 metrics:nil views:@{@"label": label}]];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[label]" options:0 metrics:nil views:@{@"label": label}]];
Etiketin yüksekliği otomatik olarak (kullanılarak intrinsicContentSize
) hesaplanır ve etiket kenardan kenara yatay olarak, üst kısmına yerleştirilir view
.
Yukarıdaki yöntemlerin çoğunu kullandım ve kullandığım hızlı ve kirli bir yaklaşımı eklemek istiyorum:
myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];
Dizedeki yeni satır sayısının herhangi bir metnin kullanılabilir dikey alanı doldurmasına neden olacağından emin olun ve UILabel'i taşan metni kesecek şekilde ayarlayın.
Çünkü bazen yeterince iyi, yeterince iyi .
UITextView
, dlopen
metin girişini desteklemek için arayabiliyor olması. Bu, UI iş parçacığında büyük gecikmeye neden olabilir, bu nedenle bu yaklaşım çok daha performanslıdır!
Çok satırlı, minimum yazı tipi boyutuna sahip olabilen ve ana görünümünde hem yatay hem de dikey olarak ortalanmış bir etikete sahip olmak istedim. Etiketimi programlı olarak görünümüme ekledim:
- (void) customInit {
// Setup label
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
self.label.numberOfLines = 0;
self.label.lineBreakMode = UILineBreakModeWordWrap;
self.label.textAlignment = UITextAlignmentCenter;
// Add the label as a subview
self.autoresizesSubviews = YES;
[self addSubview:self.label];
}
Ve sonra etiketimin metnini değiştirmek istediğimde ...
- (void) updateDisplay:(NSString *)text {
if (![text isEqualToString:self.label.text]) {
// Calculate the font size to use (save to label's font)
CGSize textConstrainedSize = CGSizeMake(self.frame.size.width, INT_MAX);
self.label.font = [UIFont systemFontOfSize:TICKER_FONT_SIZE];
CGSize textSize = [text sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
while (textSize.height > self.frame.size.height && self.label.font.pointSize > TICKER_MINIMUM_FONT_SIZE) {
self.label.font = [UIFont systemFontOfSize:self.label.font.pointSize-1];
textSize = [ticker.blurb sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
}
// In cases where the frame is still too large (when we're exceeding minimum font size),
// use the views size
if (textSize.height > self.frame.size.height) {
textSize = [text sizeWithFont:self.label.font constrainedToSize:self.frame.size];
}
// Draw
self.label.frame = CGRectMake(0, self.frame.size.height/2 - textSize.height/2, self.frame.size.width, textSize.height);
self.label.text = text;
}
[self setNeedsDisplay];
}
Umarım birine yardım eder!
(Github) FXLabel ayarlayarak kutunun bu out yapar label.contentMode
için UIViewContentModeTop
. Bu bileşen benim tarafımdan yapılmadı, ancak sık kullandığım ve tonlarca özelliğe sahip bir bileşen ve iyi çalışıyor gibi görünüyor.
etiketinizdeki metin dikey olarak ortalanmadığından bunu okuyan herkes için, bazı yazı tipi türlerinin eşit şekilde tasarlanmadığını unutmayın. örneğin, zapfino boyutu 16 olan bir etiket oluşturursanız, metnin dikey olarak tam olarak ortalanmadığını görürsünüz.
ancak helvetica ile çalışmak metninizi dikey olarak ortalar.
Kullanın textRect(forBounds:limitedToNumberOfLines:)
.
class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
super.drawText(in: textRect)
}
}
UILabel alt sınıfını çizin ve çizim dikdörtgenini şu şekilde kısıtlayın:
- (void)drawTextInRect:(CGRect)rect
{
CGSize sizeThatFits = [self sizeThatFits:rect.size];
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
[super drawTextInRect:rect];
}
Newline dolgusu içeren çözümü denedim ve bazı durumlarda yanlış davranışlarla karşılaştım. Deneyimlerime göre, çizim rektini yukarıdaki gibi kısıtlamak karışıklıktan daha kolaydır numberOfLines
.
PS UIViewContentMode'u bu şekilde kolayca desteklemeyi hayal edebilirsiniz:
- (void)drawTextInRect:(CGRect)rect
{
CGSize sizeThatFits = [self sizeThatFits:rect.size];
if (self.contentMode == UIViewContentModeTop) {
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
}
else if (self.contentMode == UIViewContentModeBottom) {
rect.origin.y = MAX(0, rect.size.height - sizeThatFits.height);
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
}
[super drawTextInRect:rect];
}
Karmaşık bir iş yapmadığınız sürece, UITextView
yerine kullanabilirsiniz UILabels
.
Kaydırma işlevini devre dışı bırakın.
Metnin tamamen görüntülenmesini istiyorsanız sadece kullanıcı sizeToFit
ve sizeThatFits:
yöntemler
Hızlıca,
let myLabel : UILabel!
Etiket metninizi ekrana sığdırmak için üstte
myLabel.sizeToFit()
Etiket yazı tipinizi ekran genişliğine veya belirli genişlik boyutuna sığdırmak için.
myLabel.adjustsFontSizeToFitWidth = YES
ve bazı metin etiketi için hizalama:
myLabel.textAlignment = .center
myLabel.textAlignment = .left
myLabel.textAlignment = .right
myLabel.textAlignment = .Natural
myLabel.textAlignment = .Justified
[myLabel sizeToFit]
. Teşekkür ederim!
Bu eski bir çözüm, iOS'ta otomatik yerleşimi kullanın> = 6
Çözümüm:
@interface UITopAlignedLabel : UILabel
@end
@implementation UITopAlignedLabel
#pragma mark Instance methods
- (NSArray*)splitTextToLines:(NSUInteger)maxLines {
float width = self.frame.size.width;
NSArray* words = [self.text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSMutableArray* lines = [NSMutableArray array];
NSMutableString* buffer = [NSMutableString string];
NSMutableString* currentLine = [NSMutableString string];
for (NSString* word in words) {
if ([buffer length] > 0) {
[buffer appendString:@" "];
}
[buffer appendString:word];
if (maxLines > 0 && [lines count] == maxLines - 1) {
[currentLine setString:buffer];
continue;
}
float bufferWidth = [buffer sizeWithFont:self.font].width;
if (bufferWidth < width) {
[currentLine setString:buffer];
}
else {
[lines addObject:[NSString stringWithString:currentLine]];
[buffer setString:word];
[currentLine setString:buffer];
}
}
if ([currentLine length] > 0) {
[lines addObject:[NSString stringWithString:currentLine]];
}
return lines;
}
- (void)drawRect:(CGRect)rect {
if ([self.text length] == 0) {
return;
}
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, self.textColor.CGColor);
CGContextSetShadowWithColor(context, self.shadowOffset, 0.0f, self.shadowColor.CGColor);
NSArray* lines = [self splitTextToLines:self.numberOfLines];
NSUInteger numLines = [lines count];
CGSize size = self.frame.size;
CGPoint origin = CGPointMake(0.0f, 0.0f);
for (NSUInteger i = 0; i < numLines; i++) {
NSString* line = [lines objectAtIndex:i];
if (i == numLines - 1) {
[line drawAtPoint:origin forWidth:size.width withFont:self.font lineBreakMode:UILineBreakModeTailTruncation];
}
else {
[line drawAtPoint:origin forWidth:size.width withFont:self.font lineBreakMode:UILineBreakModeClip];
}
origin.y += self.font.lineHeight;
if (origin.y >= size.height) {
return;
}
}
}
@end