Câu trả lời:
Không có cách nào để đặt căn chỉnh dọc trên a UILabel
, nhưng bạn có thể có được hiệu ứng tương tự bằng cách thay đổi khung của nhãn. Tôi đã làm cho nhãn của mình màu cam để bạn có thể thấy rõ những gì đang xảy ra.
Đây là cách nhanh chóng và dễ dàng để làm điều này:
[myLabel sizeToFit];
Nếu bạn có nhãn có văn bản dài hơn sẽ tạo nhiều hơn một dòng, được đặt numberOfLines
thành 0
(không ở đây có nghĩa là không giới hạn số dòng).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Phiên bản dài hơn
Tôi sẽ tạo nhãn của tôi bằng mã để bạn có thể thấy những gì đang diễn ra. Bạn cũng có thể thiết lập hầu hết điều này trong Trình tạo giao diện. Thiết lập của tôi là Ứng dụng dựa trên chế độ xem với hình nền tôi tạo bằng Photoshop để hiển thị lề (20 điểm). Nhãn có màu cam hấp dẫn để bạn có thể thấy những gì đang diễn ra với kích thước.
- (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];
}
Một số hạn chế của việc sử dụng sizeToFit
đi kèm với văn bản căn giữa hoặc phải. Đây là những gì xảy ra:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
Nhãn vẫn có kích thước với một góc trên cùng bên trái cố định. Bạn có thể lưu chiều rộng của nhãn gốc trong một biến và đặt nó sau sizeToFit
hoặc đặt chiều rộng cố định để khắc phục các vấn đề này:
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;
Lưu ý rằng sizeToFit
sẽ tôn trọng chiều rộng tối thiểu của nhãn ban đầu của bạn. Nếu bạn bắt đầu với một nhãn rộng 100 và gọi sizeToFit
nó, nó sẽ trả lại cho bạn một nhãn (có thể rất cao) với chiều rộng 100 (hoặc ít hơn một chút). Bạn có thể muốn đặt nhãn của mình thành chiều rộng tối thiểu bạn muốn trước khi thay đổi kích thước.
Một số điều khác cần lưu ý:
Việc lineBreakMode
có được tôn trọng hay không tùy thuộc vào cách thiết lập. NSLineBreakByTruncatingTail
(mặc định) được bỏ qua sau sizeToFit
, cũng như hai chế độ cắt ngắn khác (đầu và giữa). NSLineBreakByClipping
cũng bị bỏ qua. NSLineBreakByCharWrapping
hoạt động như bình thường. Chiều rộng khung hình vẫn được thu hẹp để phù hợp với chữ cái ngoài cùng bên phải.
Mark Amery đã đưa ra bản sửa lỗi cho NIB và Storyboards bằng Auto Layout trong các bình luận:
Nếu nhãn của bạn được bao gồm trong một ngòi hoặc bảng phân cảnh dưới dạng một khung nhìn phụ
view
của ViewContoder sử dụng tính năng tự động thanh toán, thìsizeToFit
cuộc gọi của bạnviewDidLoad
sẽ không hoạt động, bởi vì kích thước tự động và vị trí của các cuộc phỏng vấn sauviewDidLoad
sẽ được gọi và sẽ ngay lập tức hoàn tác các hiệu ứng của bạnsizeToFit
gọi. Tuy nhiên, gọisizeToFit
từ bên trongviewDidLayoutSubviews
sẽ làm việc.
Điều này sử dụng NSString
phương pháp sizeWithFont:constrainedToSize:lineBreakMode:
để tính chiều cao khung cần thiết để khớp với một chuỗi, sau đó đặt gốc và chiều rộng.
Thay đổi kích thước khung cho nhãn bằng văn bản bạn muốn chèn. Bằng cách đó bạn có thể chứa bất kỳ số lượng dòng.
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
thì hãy sử dụng sizeToFit, sau đó đặt khung của nhãn thành 0, 0, theWidthYouWant, nhãn.frame.size.height (là chiều cao mới được xác định bởi sizeToFit) THEN áp dụngadjustsFontSizeToFitWidth
Đặt văn bản mới:
myLabel.text = @"Some Text"
Đặt các maximum number
dòng thành 0 (tự động):
myLabel.numberOfLines = 0
Đặt khung của nhãn thành kích thước tối đa:
myLabel.frame = CGRectMake(20,20,200,800)
Gọi sizeToFit
để giảm kích thước khung hình để nội dung vừa vặn:
[myLabel sizeToFit]
Khung nhãn bây giờ chỉ cao và đủ rộng để phù hợp với văn bản của bạn. Phía trên bên trái nên không thay đổi. Tôi đã thử nghiệm điều này chỉ với văn bản liên kết bên trái trên cùng. Đối với các sắp xếp khác, bạn có thể phải sửa đổi khung sau đó.
Ngoài ra, nhãn của tôi có kích hoạt gói từ.
Đề cập đến giải pháp mở rộng:
for(int i=1; i< newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n"];
nên được thay thế bởi
for(int i=0; i<newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n "];
Cần thêm không gian trong mỗi dòng mới được thêm vào, bởi vì UILabels
lợi nhuận vận chuyển kéo dài của iPhone dường như bị bỏ qua :(
Tương tự, alignBottom cũng nên được cập nhật @" \n@%"
thay cho "\n@%"
(để khởi tạo chu kỳ phải được thay thế bằng "for (int i = 0 ...").
Phần mở rộng sau đây hoạt động với tôi:
// -- 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
Sau đó gọi [yourLabel alignTop];
hoặc [yourLabel alignBottom];
sau mỗi lần gán văn bản của bạn.
VerticalAlign
giữa dấu ngoặc đơn sau @implementation UILabel
. Là người mới đối với Objective-C Tôi chưa từng chạy qua cú pháp này trước đây. Cái này gọi là gì?
sizeWithFont:constrainedToSize:lineBreakMode:
và sizeWithFont: đều bị khấu hao trong iOS7. Ngoài ra, danh mục này chỉ hoạt động trên nhãn khi numberOfLines lớn hơn 0.
Chỉ trong trường hợp có bất kỳ sự giúp đỡ nào cho bất kỳ ai, tôi cũng gặp vấn đề tương tự nhưng có thể giải quyết vấn đề chỉ bằng cách chuyển từ sử dụng UILabel
sang sử dụng UITextView
. Tôi đánh giá cao điều này không dành cho tất cả mọi người vì chức năng hơi khác một chút.
Nếu bạn chuyển sang sử dụng UITextView
, bạn có thể tắt tất cả các thuộc tính Chế độ xem cuộn cũng như Kích hoạt tương tác người dùng ... Điều này sẽ buộc nó hoạt động giống như một nhãn.
UITextView
đã cho tôi kết quả mong muốn ngay lập tức.
Không ồn ào, không ồn ào
@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
Không ồn ào, không khách quan-c, không ồn ào nhưng 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)
}
}
Giống như câu trả lời ở trên, nhưng nó không hoàn toàn đúng, hoặc dễ dàng đưa vào mã để tôi dọn dẹp nó một chút. Thêm tiện ích mở rộng này vào tệp .h và .m của chính nó hoặc chỉ cần dán ngay phía trên triển khai bạn định sử dụng:
#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
Và sau đó để sử dụng, hãy đặt văn bản của bạn vào nhãn và sau đó gọi phương thức thích hợp để căn chỉnh nó:
[myLabel alignTop];
hoặc là
[myLabel alignBottom];
Một cách thậm chí nhanh hơn (và bẩn hơn) để thực hiện điều này là bằng cách đặt chế độ ngắt dòng của UILabel thành "Clip" và thêm một số dòng mới cố định.
myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];
Giải pháp này sẽ không hiệu quả với tất cả mọi người - đặc biệt, nếu bạn vẫn muốn hiển thị "..." ở cuối chuỗi nếu vượt quá số dòng bạn đang hiển thị, bạn sẽ cần sử dụng một trong những các đoạn mã dài hơn - nhưng trong nhiều trường hợp, điều này sẽ giúp bạn có được thứ bạn cần.
UILineBreakModeWordWrap
thay thế.
Cách tiếp cận dễ nhất bằng Storyboard:
Nhúng nhãn trong StackView và đặt theo hai thuộc tính của StackView trong Trình theo dõi thuộc tính:
1- Axis
đến Horizontal
,
2 Alignment
đếnTop
UILabel
vào một số UIView
lớp con ( UIView
thường là đủ) và để cho nhãn đó phát triển theo hướng xuống. Cảm ơn!
UILabel
và để StackView thực hiện công việc của mình. Cảm ơn!
Thay vì UILabel
bạn có thể sử dụng UITextField
có tùy chọn căn chỉnh dọc:
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction
Tôi đã vật lộn với điều này trong một thời gian dài và tôi muốn chia sẻ giải pháp của mình.
Điều này sẽ cung cấp cho bạn một UILabel
văn bản sẽ tự động thu nhỏ văn bản xuống 0,5 tỷ lệ và căn giữa văn bản theo chiều dọc. Các tùy chọn này cũng có sẵn trong Storyboard / IB.
[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
Tạo một lớp mới
NhãnTopAlign
tập tin .h
#import <UIKit/UIKit.h>
@interface KwLabelTopAlign : UILabel {
}
@end
tập tin .m
#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
Đây là một cách thực hiện đơn giản hơn, thực hiện tương tự:
#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
giải pháp, điều này thực sự làm cho việc UILabel
đặt bất kỳ văn bản nào lên hàng đầu, ngay cả khi bạn tự động thay thế một văn bản ngắn hơn bằng một văn bản dài hơn hoặc ngược lại.
Trong Trình tạo giao diện
UILabel
kích thước của Văn bản lớn nhất có thểLines
thành '0' trong Trình theo dõi thuộc tínhTrong mã của bạn
sizeToFit
vào nhãn của bạnĐoạn mã:
self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
Đối với Giao diện người dùng thích ứng (iOS8 trở lên), Sắp xếp theo chiều dọc của UILabel sẽ được đặt từ StoryBoard bằng cách thay đổi các thuộc tính
noOfLines
= 0` và
Những ràng buộc
Điều chỉnh UILabel LefMargin, RightMargin và các ràng buộc ký quỹ hàng đầu.
Thay đổi
Content Compression Resistance Priority For Vertical
= 1000` Vì vậy mà dọc> ngang.
Đã chỉnh sửa:
noOfLines=0
và các ràng buộc sau đây là đủ để đạt được kết quả mong muốn.
Tạo một lớp con của UILabel. Hoạt động như một lá bùa:
// 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
Như đã thảo luận ở đây .
Tôi đã viết một chức năng để đạt được mục đích này. Bạn có thể xem:
// điều chỉnh chiều cao của nhãn nhiều dòng để làm cho nó thẳng hàng với đỉnh + (void) alignLabelWithTop: (UILabel *) nhãn { CGSize maxSize = CGSizeMake (nhãn.frame.size. Thong, 999); nhãn.adjowersFontSizeToFitWidth = NO; // lấy chiều cao thực tế CGSize factSize = [nhãn.text sizeWithFont: nhãn.font ràng buộcToSize: maxSize lineBreakMode: nhãn.lineBreakMode]; CGRect orth = nhãn.frame; orth.size.height = factSize.height; nhãn.frame = orth; }
Làm thế nào để sử dụng? (Nếu lblHello được tạo bởi Trình xây dựng giao diện, vì vậy tôi bỏ qua một số chi tiết thuộc tính UILabel)
lblHello.text = @ "Xin chào thế giới! Xin chào thế giới! Xin chào thế giới! Xin chào thế giới! Xin chào thế giới! Xin chào thế giới! Xin chào thế giới! Xin chào thế giới!"; lblHello.numberOfLines = 5; [Sử dụng alignLabelWithTop: lblHello];
Tôi cũng đã viết nó trên blog của mình dưới dạng một bài viết: http://fstoke.me/blog/?p=2819
Tôi đã mất một lúc để đọc mã, cũng như mã trong trang được giới thiệu và thấy rằng tất cả họ đều cố gắng sửa đổi kích thước khung của nhãn, để căn chỉnh dọc trung tâm mặc định sẽ không xuất hiện.
Tuy nhiên, trong một số trường hợp, chúng tôi muốn nhãn chiếm hết tất cả các khoảng trắng đó, ngay cả khi nhãn có quá nhiều văn bản (ví dụ: nhiều hàng có chiều cao bằng nhau).
Ở đây, tôi đã sử dụng một cách khác để giải quyết nó, bằng cách đơn giản là điền các dòng mới vào cuối nhãn (xin lưu ý rằng tôi thực sự được thừa hưởng UILabel
, nhưng nó không cần thiết):
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 "];
}
Tôi đã lấy các đề xuất ở đây và tạo ra một khung nhìn có thể bao bọc một UILabel và sẽ kích thước nó và đặt số lượng dòng sao cho nó được căn chỉnh hàng đầu. Đơn giản chỉ cần đặt một UILabel làm một cuộc phỏng vấ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
Bạn có thể sử dụng TTTAttributionLabel , nó hỗ trợ căn chỉnh dọc.
@property (nonatomic) TTTAttributedLabel* label;
<...>
//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
Tôi đã tìm thấy câu trả lời cho câu hỏi này hiện đã hơi lỗi thời, vì vậy, thêm câu hỏi này cho người hâm mộ bố trí tự động ngoài kia.
Bố trí tự động làm cho vấn đề này khá nhỏ. Giả sử chúng ta thêm nhãn vào UIView *view
, đoạn mã sau sẽ thực hiện điều này:
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}]];
Chiều cao của nhãn sẽ được tính toán tự động (sử dụng nó intrinsicContentSize
) và nhãn sẽ được đặt theo chiều ngang từ trên xuống theo chiều ngang, ở trên cùng của view
.
Tôi đã sử dụng rất nhiều phương pháp ở trên và chỉ muốn thêm một cách tiếp cận nhanh và bẩn mà tôi đã sử dụng:
myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];
Đảm bảo số lượng dòng mới trong chuỗi sẽ khiến bất kỳ văn bản nào lấp đầy không gian dọc có sẵn và đặt UILabel để cắt bớt bất kỳ văn bản tràn nào.
Bởi vì đôi khi đủ tốt là đủ tốt .
UITextView
nó là nó có thể gọi dlopen
để hỗ trợ nhập văn bản. Điều này có thể gây ra độ trễ lớn trên luồng UI, vì vậy cách tiếp cận này hiệu quả hơn nhiều!
Tôi muốn có một nhãn có thể có nhiều dòng, cỡ chữ tối thiểu và được căn giữa cả theo chiều ngang và chiều dọc trong chế độ xem chính. Tôi đã thêm nhãn của mình theo chương trình vào quan điểm của mình:
- (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];
}
Và sau đó khi tôi muốn thay đổi văn bản của nhãn của mình ...
- (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];
}
Mong rằng sẽ giúp được ai đó!
FXLabel (trên github) thực hiện việc này ngoài hộp bằng cách đặt label.contentMode
thành UIViewContentModeTop
. Thành phần này không phải do tôi tạo ra, nhưng nó là thành phần tôi sử dụng thường xuyên và có hàng tấn tính năng, và dường như hoạt động tốt.
đối với bất kỳ ai đọc điều này bởi vì văn bản bên trong nhãn của bạn không được căn giữa theo chiều dọc, hãy nhớ rằng một số loại phông chữ không được thiết kế như nhau. ví dụ: nếu bạn tạo nhãn có kích thước zapfino 16, bạn sẽ thấy văn bản không được căn giữa hoàn hảo theo chiều dọc.
tuy nhiên, làm việc với helvetica sẽ tập trung vào văn bản của bạn theo chiều dọc.
Sử dụng textRect(forBounds:limitedToNumberOfLines:)
.
class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
super.drawText(in: textRect)
}
}
Phân lớp UILabel và hạn chế hình chữ nhật vẽ, như thế này:
- (void)drawTextInRect:(CGRect)rect
{
CGSize sizeThatFits = [self sizeThatFits:rect.size];
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
[super drawTextInRect:rect];
}
Tôi đã thử giải pháp liên quan đến phần đệm dòng mới và gặp phải hành vi không chính xác trong một số trường hợp. Theo kinh nghiệm của tôi, việc hạn chế bản vẽ như trên sẽ dễ dàng hơn so với lộn xộn numberOfLines
.
PS Bạn có thể tưởng tượng dễ dàng hỗ trợ UIViewContentMode theo cách này:
- (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];
}
Nhanh chóng
let myLabel : UILabel!
Để làm cho văn bản Nhãn của bạn vừa với màn hình và nó ở trên cùng
myLabel.sizeToFit()
Để làm cho phông chữ của nhãn của bạn vừa với chiều rộng của màn hình hoặc kích thước chiều rộng cụ thể.
myLabel.adjustsFontSizeToFitWidth = YES
và một số văn bản Sắp xếp cho nhãn:
myLabel.textAlignment = .center
myLabel.textAlignment = .left
myLabel.textAlignment = .right
myLabel.textAlignment = .Natural
myLabel.textAlignment = .Justified
[myLabel sizeToFit]
. Cảm ơn bạn!
Đây là một giải pháp cũ, hãy sử dụng tính năng tự động thanh toán trên iOS> = 6
Giải pháp của tôi:
@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