Saya memiliki UILabel
dengan ruang untuk dua baris teks. Kadang-kadang, ketika teks ini terlalu singkat, teks ini akan ditampilkan di tengah vertikal label.
Bagaimana saya secara vertikal menyelaraskan teks untuk selalu berada di atas UILabel
?
Ada's tidak ada cara untuk mengatur vertical-align pada UILabel
, tapi anda bisa mendapatkan efek yang sama dengan mengubah label's frame. I've membuat label orange sehingga anda dapat melihat dengan jelas apa yang's terjadi.
Berikut ini's cara cepat dan mudah untuk melakukan hal ini:
[myLabel sizeToFit];
Jika anda memiliki label dengan teks yang lebih panjang yang akan membuat lebih dari satu baris, set numberOfLines
ke 0
(nol di sini berarti jumlah yang tidak terbatas dari garis-garis).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Versi Lama
I'll membuat label di kode sehingga anda dapat melihat apa yang's terjadi. Anda dapat mengatur ini di Interface Builder juga. Setup saya adalah Pandangan Berbasis Aplikasi, dengan gambar latar belakang saya membuat di Photoshop untuk menunjukkan margin (20 poin). Label yang menarik warna orange sehingga anda dapat melihat apa yang's terjadi dengan dimensi.
- (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];
}
Beberapa keterbatasan menggunakan sizeToFit
datang ke dalam bermain dengan pusat - atau kanan-blok teks. Berikut ini's apa yang terjadi:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
Label masih berukuran dengan tetap pojok kiri atas. Anda dapat menyimpan label asli's lebar dalam sebuah variabel dan set itu setelah sizeToFit
, atau memberikan fixed width untuk mengatasi masalah ini:
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;
Perhatikan bahwa sizeToFit
akan menghormati awal anda label's lebar minimum. Jika anda memulai dengan label 100 lebar dan panggilan sizeToFit
di atasnya, itu akan memberikan anda kembali (mungkin terlalu tinggi) label dengan 100 (atau kurang) lebar. Anda mungkin ingin mengatur label untuk lebar minimum yang anda inginkan sebelum mengubah ukuran.
Beberapa hal-hal lain untuk catatan:
Apakah lineBreakMode
dihormati tergantung pada bagaimana hal itu's set. NSLineBreakByTruncatingTail
(default) diabaikan setelah sizeToFit
, karena dua yang lain pemotongan mode (kepala dan tengah). NSLineBreakByClipping
juga diabaikan. NSLineBreakByCharWrapping
bekerja seperti biasa. Lebar frame masih menyempit untuk masuk ke paling kanan surat.
Mark Amery memberikan fix untuk NIBs dan Storyboard menggunakan Auto tata Letak di komentar:
Jika anda label ini termasuk dalam nib atau storyboard sebagai subview dari
melihat
dari ViewController yang menggunakan autolayout, kemudian menempatkansizeToFit
panggilviewDidLoad
tidak't bekerja, karena autolayout ukuran dan posisi subviews setelahviewDidLoad
disebut dan akan segera membatalkan efek darisizeToFit
call. Namun, memanggilsizeToFit
dari dalamviewDidLayoutSubviews
akan bekerja.
Ini menggunakan NSString
metode sizeWithFont:constrainedToSize:lineBreakMode:
untuk menghitung frame tinggi yang dibutuhkan untuk memenuhi string, kemudian menetapkan asal-usul dan lebar.
Mengubah ukuran frame untuk label menggunakan teks yang ingin anda masukkan. Dengan cara itu anda dapat menampung jumlah baris.
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;
myLabel.text = @"Text"
jumlah maksimum
dari baris ke 0 (otomatis):myLabel.numberOfLines = 0
myLabel.frame = CGRectMake(20,20,200,800)
sizeToFit
untuk mengurangi ukuran frame jadi isi saja sesuai:[myLabel sizeToFit]
Label frame sekarang hanya tinggi dan cukup lebar untuk cocok untuk teks anda. Kiri atas harus berubah. Saya telah diuji ini hanya dengan bagian atas kiri-blok teks. Untuk keberpihakan, anda mungkin harus mengubah frame sesudahnya.
Juga, saya memiliki label pembungkus kata diaktifkan.
Mengacu pada ekstensi solusi:
for(int i=1; i< newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n"];
harus diganti dengan
for(int i=0; i<newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n "];
Ruang tambahan diperlukan di setiap menambahkan baris baru, karena iPhone UILabels
' tertinggal kereta kembali tampaknya diabaikan :(
Demikian pula, alignBottom harus diperbarui juga dengan @" \n@%"
di tempat "\n@%"
(untuk siklus inisialisasi harus diganti dengan "for(int i=0..." juga).
Berikut ekstensi bekerja untuk saya:
// -- 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
Kemudian memanggil [yourLabel alignTop];
atau [yourLabel alignBottom];
setelah setiap yourLabel teks tugas.
Hanya dalam kasus itu's bantuan apa pun kepada siapa pun, aku punya masalah yang sama tapi mampu memecahkan masalah hanya dengan beralih dari menggunakan UILabel
menggunakan UITextView
. Saya menghargai ini isn't untuk semua orang karena fungsi yang sedikit berbeda.
Jika anda beralih untuk menggunakan UITextView
, anda dapat mematikan semua Gulir Melihat sifat serta Interaksi Pengguna Diaktifkan... Ini akan memaksa untuk bertindak lebih seperti label.
Tidak ada pertengkaran, tidak ada ribut-ribut
@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
Tidak ada pertengkaran, tidak ada Objective-c, tidak ada ribut-ribut tapi 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)
}
}
Swift 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)
}
}
Seperti jawaban di atas, tapi itu bukan't cukup tepat, atau mudah untuk menampar ke dalam kode-kode agar aku membersihkannya sedikit. Tambahkan ekstensi ini baik untuk itu's sendiri .jam dan .m file atau hanya paste tepat di atas terselenggaranya anda berniat untuk menggunakannya:
#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
Dan kemudian untuk menggunakan, menempatkan teks anda ke label, dan kemudian memanggil metode yang sesuai untuk menyelaraskan ini:
[myLabel alignTop];
atau
[myLabel alignBottom];
Bahkan lebih cepat (dan lebih kotor) cara untuk mencapai hal ini adalah dengan menetapkan UILabel's line mode istirahat untuk "Klip", dan menambahkan jumlah yang tetap dari baris baru.
myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];
Solusi ini tidak't bekerja untuk semua orang -- khususnya, jika anda masih ingin menunjukkan "..." pada akhir dari string anda jika melebihi jumlah baris yang anda're menunjukkan, anda'll perlu menggunakan salah satu dari panjang bit dari kode-tetapi untuk banyak kasus ini'll membuat anda mendapatkan apa yang anda butuhkan.
Bukan UILabel
anda dapat menggunakan UITextField
yang telah vertikal keselarasan pilihan:
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction
I've berjuang dengan yang satu ini untuk waktu yang lama dan saya ingin berbagi solusi saya.
Ini akan memberikan anda sebuah UILabel
yang akan penciutan otomatis teks turun ke 0,5 timbangan dan vertikal pusat teks. Opsi ini juga tersedia dalam Storyboard/IB.
[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
Membuat class baru
LabelTopAlign
.h file
#import <UIKit/UIKit.h>
@interface KwLabelTopAlign : UILabel {
}
@end
.m file
#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
Berikut ini's sederhana implementasi yang tidak sama:
#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
Di Interface Builder
UILabel
untuk ukuran terbesar mungkin TeksGaris
untuk '0' di Atribut InspekturDalam kode anda
sizeToFit
pada label andaPotongan Kode:
self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
Untuk Adaptif UI(iOS8 atau setelah) , Vertikal Keselarasan UILabel harus ditetapkan dari StoryBoard dengan Mengubah properti
noOfLines
=0` dan
Kendala
Menyesuaikan UILabel LefMargin, RightMargin dan Margin Atas Kendala.
Perubahan
Konten Ketahanan Kompresi Prioritas Untuk Vertikal
=1000` Sehingga Vertikal>Horisontal .
Edited:
noOfLines=0
dan berikut kendala-kendala yang cukup untuk mencapai hasil yang diinginkan.
Membuat subclass dari UILabel. Bekerja seperti pesona:
// 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
Seperti yang dibahas di sini.
Saya menulis util fungsi untuk mencapai tujuan ini. Anda dapat melihat:
// sesuaikan tinggi multi-line label untuk membuat menyelaraskan vertikal dengan top + (void) alignLabelWithTop:(UILabel *)label { CGSize maxSize = CGSizeMake(label.frame.ukuran.lebar, 999); label.adjustsFontSizeToFitWidth = TIDAK ada;// mendapatkan ketinggian yang sebenarnya CGSize actualSize = [label.teks sizeWithFont:label.font constrainedToSize:maxSize lineBreakMode:label.lineBreakMode]; CGRect rect = label.bingkai; rect.ukuran.tinggi = actualSize.tinggi; label.frame = rect; }
.Bagaimana untuk digunakan? (Jika lblHello dibuat oleh pembangun Antarmuka, jadi saya melewatkan beberapa UILabel atribut detail)
lblHello.text = @"Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!"; lblHello.numberOfLines = 5; [Utils alignLabelWithTop:lblHello];
Saya juga menulis di blog saya sebagai sebuah artikel: http://fstoke.me/blog/?p=2819
Aku butuh waktu beberapa saat untuk membaca kode, serta kode diperkenalkan halaman, dan menemukan bahwa mereka semua mencoba untuk mengubah ukuran frame label, sehingga default center alignment vertikal tidak akan muncul.
Namun, dalam beberapa kasus kita tidak ingin label untuk menempati semua ruang-ruang tersebut, bahkan jika label tidak memiliki begitu banyak teks (misalnya beberapa baris dengan sama tinggi).
Di sini, saya menggunakan cara alternatif untuk memecahkan hal itu, hanya dengan pad baris akhir dari label (pls dicatat bahwa saya benar-benar mewarisi UILabel
, tapi hal ini tidak perlu):
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 "];
}
Aku mengambil saran-saran berikut ini dan menciptakan sebuah tampilan yang dapat membungkus UILabel dan akan ukuran dan mengatur jumlah baris agar lebih selaras. Hanya menempatkan UILabel sebagai subview:
@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
Anda dapat menggunakan TTTAttributedLabel, mendukung vertikal keselarasan.
@property (nonatomic) TTTAttributedLabel* label;
<...>
//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
I've digunakan banyak metode-metode di atas, dan hanya ingin menambahkan cepat-dan-kotor pendekatan I've digunakan:
myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];
Pastikan jumlah baris baru dalam string akan menyebabkan teks untuk mengisi ruang vertikal yang tersedia, dan mengatur UILabel untuk memotong setiap meluap teks.
Karena kadang-kadang cukup baik sangat cukup.
I've menemukan jawaban pada pertanyaan ini yang sekarang sedikit out-of-date, sehingga menambahkan ini untuk auto tata letak penggemar di luar sana.
Auto tata letak yang membuat masalah ini cukup sepele. Dengan asumsi kita're menambahkan label untuk UIView *view
, kode berikut akan mencapai hal ini:
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}]];
Label's tinggi akan dihitung secara otomatis (menggunakan it's intrinsicContentSize
) dan label akan diposisikan di tepi-ke-tepi horizontal, di atas melihat
.