Отрегулируйте высоту UILabel в зависимости от текста
Считайте, что у меня есть следующий текст в UILabel
(длинная строка динамического текста):
Так как армия инопланетян значительно превосходит численность команды, игроки должны использовать постапокалиптический мир в своих интересах, таких как поиск укрытия за мусорными контейнерами, колоннами, машинами, обломками и другими объектами.
Я хочу изменить размер UILabel's
высота, чтобы текст мог поместиться. Я использую следующие свойства UILabel
сделать текст внутри, чтобы обернуть.
myUILabel.lineBreakMode = UILineBreakModeWordWrap;
myUILabel.numberOfLines = 0;
Пожалуйста, дайте мне знать, если я не в правильном направлении. Благодарю.
34 ответа
sizeWithFont constrainedToSize:lineBreakMode:
это метод для использования. An example of how to use it is below:
//Calculate the expected size based on the font and linebreak mode of your label
// FLT_MAX here simply means no constraint in height
CGSize maximumLabelSize = CGSizeMake(296, FLT_MAX);
CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font constrainedToSize:maximumLabelSize lineBreakMode:yourLabel.lineBreakMode];
//adjust the label the the new height.
CGRect newFrame = yourLabel.frame;
newFrame.size.height = expectedLabelSize.height;
yourLabel.frame = newFrame;
Вы шли в правильном направлении. Все, что вам нужно сделать, это:
myUILabel.numberOfLines = 0;
myUILabel.text = @"Enter large amount of text here";
[myUILabel sizeToFit];
В iOS 6 Apple добавила свойство в UILabel, которое значительно упрощает динамическое вертикальное изменение размера меток: предпочитается MaxLayoutWidth.
Использование этого свойства в сочетании с lineBreakMode = NSLineBreakByWordWrapping и методом sizeToFit позволяет легко изменять размер экземпляра UILabel до высоты, в которой помещается весь текст.
Цитата из документации iOS:
предпочитаемая максимальная ширина Максимальная ширина (в точках) для многострочной метки.
Обсуждение Это свойство влияет на размер метки, когда к ней применяются ограничения макета. Если во время макета текст выходит за пределы ширины, заданной этим свойством, дополнительный текст передается одной или нескольким новым строкам, что увеличивает высоту метки.
Образец:
...
UILabel *status = [[UILabel alloc] init];
status.lineBreakMode = NSLineBreakByWordWrapping;
status.numberOfLines = 5; // limits to 5 lines; use 0 for unlimited.
[self addSubview:status]; // self here is the parent view
status.preferredMaxLayoutWidth = self.frame.size.width; // assumes the parent view has its frame already set.
status.text = @"Some quite lengthy message may go here…";
[status sizeToFit];
[status setNeedsDisplay];
...
Проверьте эту работу отлично без добавления одной строки кода. (Используя Autolayout)
Я сделал демо для вас по вашему требованию. Скачать его по ссылке ниже,
Пошаговое руководство: -
Шаг 1:- Установите ограничение на UIView
1) Ведущий 2) Топ 3) Трейлинг (Из основного обзора)
Шаг 2:- Установите ограничение на метку 1
1) Ведущие 2) Топ 3) Трейлинг (Из супер-просмотра)
Шаг 3:- Установите ограничение на метку 2
1) Ведущий 2) Трейлинг (Из супер-просмотра)
Шаг 4:- Сложнеевсего дать Боттону UILabel из UIView .
Шаг 5: - (Необязательно) Установите ограничение на UIButton
1) Ведущий 2) Низ 3) Трейлинг 4) Фиксированная высота (из основного обзора)
Выход:-
Примечание: - Убедитесь, что вы установили Number of lines =0 в свойстве Label.
Я надеюсь, что этой информации достаточно, чтобы понять Autoresize UIView в соответствии с высотой UILabel и Autoresize UILabel в соответствии с текстом.
Вместо того, чтобы делать это программно, вы можете сделать это в Storyboard/XIB во время проектирования.
- Установите для свойства количества строк UIlabel значение 0 в инспекторе атрибутов.
- Затем установите ограничение ширины /(или) начальное и конечное ограничение согласно требованию.
- Затем установите ограничение по высоте с минимальным значением. Наконец, выберите добавленное ограничение высоты и в инспекторе размера, расположенном рядом с инспектором атрибутов, измените отношение ограничения высоты с равно на - больше, чем.
Спасибо, ребята, за помощь, вот код, который я пробовал, который работает для меня
UILabel *instructions = [[UILabel alloc]initWithFrame:CGRectMake(10, 225, 300, 180)];
NSString *text = @"First take clear picture and then try to zoom in to fit the ";
instructions.text = text;
instructions.textAlignment = UITextAlignmentCenter;
instructions.lineBreakMode = NSLineBreakByWordWrapping;
[instructions setTextColor:[UIColor grayColor]];
CGSize expectedLabelSize = [text sizeWithFont:instructions.font
constrainedToSize:instructions.frame.size
lineBreakMode:UILineBreakModeWordWrap];
CGRect newFrame = instructions.frame;
newFrame.size.height = expectedLabelSize.height;
instructions.frame = newFrame;
instructions.numberOfLines = 0;
[instructions sizeToFit];
[self addSubview:instructions];
Решение iOS7 до и iOS7 выше
//
// UILabel+DynamicHeight.m
// For StackOverFlow
//
// Created by Vijay on 24/02/14.
// Copyright (c) 2014 http://Vijay-Apple-Dev.blogspot.com. All rights reserved.
//
#import <UIKit/UIKit.h>
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define iOS7_0 @"7.0"
@interface UILabel (DynamicHeight)
/*====================================================================*/
/* Calculate the size,bounds,frame of the Multi line Label */
/*====================================================================*/
/**
* Returns the size of the Label
*
* @param aLabel To be used to calculte the height
*
* @return size of the Label
*/
-(CGSize)sizeOfMultiLineLabel;
@end
//
// UILabel+DynamicHeight.m
// For StackOverFlow
//
// Created by Vijay on 24/02/14.
// Copyright (c) 2014 http://Vijay-Apple-Dev.blogspot.com. All rights reserved.
//
#import "UILabel+DynamicHeight.h"
@implementation UILabel (DynamicHeight)
/*====================================================================*/
/* Calculate the size,bounds,frame of the Multi line Label */
/*====================================================================*/
/**
* Returns the size of the Label
*
* @param aLabel To be used to calculte the height
*
* @return size of the Label
*/
-(CGSize)sizeOfMultiLineLabel{
NSAssert(self, @"UILabel was nil");
//Label text
NSString *aLabelTextString = [self text];
//Label font
UIFont *aLabelFont = [self font];
//Width of the Label
CGFloat aLabelSizeWidth = self.frame.size.width;
if (SYSTEM_VERSION_LESS_THAN(iOS7_0)) {
//version < 7.0
return [aLabelTextString sizeWithFont:aLabelFont
constrainedToSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
lineBreakMode:NSLineBreakByWordWrapping];
}
else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(iOS7_0)) {
//version >= 7.0
//Return the calculated size of the Label
return [aLabelTextString boundingRectWithSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{
NSFontAttributeName : aLabelFont
}
context:nil].size;
}
return [self bounds].size;
}
@end
Так как sizeWithFont устарела, я использую этот вместо.
этот получает специфичные для метки атрибуты.
-(CGFloat)heightForLabel:(UILabel *)label withText:(NSString *)text{
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:@{NSFontAttributeName:label.font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){label.frame.size.width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
return ceil(rect.size.height);
}
Расширение UILabel на основе этого ответа для Swift 4 и выше
extension UILabel {
func retrieveTextHeight () -> CGFloat {
let attributedText = NSAttributedString(string: self.text!, attributes: [NSFontAttributeName:self.font])
let rect = attributedText.boundingRect(with: CGSize(width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil)
return ceil(rect.size.height)
}
}
Может использоваться как:
self.labelHeightConstraint.constant = self.label.retrieveTextHeight()
Вот версия категории:
UILabel + AutoSize.h #import
@interface UILabel (AutoSize)
- (void) autosizeForWidth: (int) width;
@end
UILabel + AutoSize.m
#import "UILabel+AutoSize.h"
@implementation UILabel (AutoSize)
- (void) autosizeForWidth: (int) width {
self.lineBreakMode = UILineBreakModeWordWrap;
self.numberOfLines = 0;
CGSize maximumLabelSize = CGSizeMake(width, FLT_MAX);
CGSize expectedLabelSize = [self.text sizeWithFont:self.font constrainedToSize:maximumLabelSize lineBreakMode:self.lineBreakMode];
CGRect newFrame = self.frame;
newFrame.size.height = expectedLabelSize.height;
self.frame = newFrame;
}
@end
Вы можете реализовать TableViewController's
(UITableViewCell *)tableView:cellForRowAtIndexPath
метод следующим образом (например):
#define CELL_LABEL_TAG 1
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *text = @"my long text";
static NSString *MyIdentifier = @"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:identifier] autorelease];
}
CGFloat width = [UIScreen mainScreen].bounds.size.width - 50;
CGFloat height = [self textHeight:text] + 10;
CGRect frame = CGRectMake(10.0f, 10.0f, width, height);
UILabel *cellLabel = [[UILabel alloc] initWithFrame:frame];
cellLabel.tag = CELL_LABEL_TAG;
cellLabel.textColor = [UIColor blackColor];
cellLabel.backgroundColor = [UIColor clearColor];
cellLabel.textAlignment = UITextAlignmentLeft;
cellLabel.font = [UIFont systemFontOfSize:12.0f];
[cell.contentView addSubview:cellLabel];
[cellLabel release];
return cell;
}
UILabel *label = (UILabel *)[cell viewWithTag:CELL_LABEL_TAG];
label.text = text;
label.numberOfLines = 0;
[label sizeToFit];
return cell;
Также используйте NSString
"s sizeWithFont:constrainedToSize:lineBreakMode:
метод для вычисления высоты текста.
Мой подход к вычислению динамической высоты UILabel.
let width = ... //< width of this label
let text = ... //< display content
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.preferredMaxLayoutWidth = width
// Font of this label.
//label.font = UIFont.systemFont(ofSize: 17.0)
// Compute intrinsicContentSize based on font, and preferredMaxLayoutWidth
label.invalidateIntrinsicContentSize()
// Destination height
let height = label.intrinsicContentSize.height
Обернуть, чтобы функционировать:
func computeHeight(text: String, width: CGFloat) -> CGFloat {
// A dummy label in order to compute dynamic height.
let label = UILabel()
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.font = UIFont.systemFont(ofSize: 17.0)
label.preferredMaxLayoutWidth = width
label.text = text
label.invalidateIntrinsicContentSize()
let height = label.intrinsicContentSize.height
return height
}
Вы можете получить высоту, используя код ниже
Вы должны пройти
текст 2. шрифт 3. ширина метки
func heightForLabel(text: String, font: UIFont, width: CGFloat) -> CGFloat { let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude)) label.numberOfLines = 0 label.lineBreakMode = NSLineBreakMode.byWordWrapping label.font = font label.text = text label.sizeToFit() return label.frame.height }
Самый простой и лучший способ, который сработал для меня, - это применить ограничение высоты к метке и установить приоритет на низкий уровень, т. Е. (250) в раскадровке.
Так что вам не нужно беспокоиться о программном расчете высоты и ширины благодаря раскадровке.
А для тех, кто мигрирует на iOS 8, вот расширение класса для Swift:
extension UILabel {
func autoresize() {
if let textNSString: NSString = self.text {
let rect = textNSString.boundingRectWithSize(CGSizeMake(self.frame.size.width, CGFloat.max),
options: NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: [NSFontAttributeName: self.font],
context: nil)
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, rect.height)
}
}
}
Обновленный метод
+ (CGFloat)heightForText:(NSString*)text font:(UIFont*)font withinWidth:(CGFloat)width {
CGSize constraint = CGSizeMake(width, 20000.0f);
CGSize size;
CGSize boundingBox = [text boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:font}
context:nil].size;
size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));
return size.height;
}
Это одна строка кода для получения высоты UILabel с помощью Objective-c:
labelObj.numberOfLines = 0;
CGSize neededSize = [labelObj sizeThatFits:CGSizeMake(screenWidth, CGFLOAT_MAX)];
и используя.height вы получите высоту метки следующим образом:
neededSize.height
Свифт 2:
yourLabel.text = "your very long text"
yourLabel.numberOfLines = 0
yourLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
yourLabel.frame.size.width = 200
yourLabel.frame.size.height = CGFloat(MAXFLOAT)
yourLabel.sizeToFit()
Интересные строки sizeToFit()
в сочетании с установкой frame.size.height
до максимального числа, это даст место для длинного текста, но sizeToFit()
заставит его использовать только необходимое, но ВСЕГДА вызывать его после установки .frame.size.height
,
Я рекомендую установить .backgroundColor
в целях отладки, таким образом, вы можете видеть, как кадр отображается для каждого случая.
Добавление к ответам выше:
Это может быть легко достигнуто через раскадровку.
- Установите ограничение для UILabel.(В моем случае я сделал верхнюю, левую и фиксированную ширину)
- Установите номер строки в 0 в инспекторе атрибутов
- Установите разрыв строки в WordWrap в инспекторе атрибутов.
Для этого в Swift3 следующий код:
let labelSizeWithFixedWith = CGSize(width: 300, height: CGFloat.greatestFiniteMagnitude)
let exactLabelsize = self.label.sizeThatFits(labelSizeWithFixedWith)
self.label.frame = CGRect(origin: CGPoint(x: 20, y: 20), size: exactLabelsize)
UILabel *itemTitle = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 10,100, 200.0f)];
itemTitle.text = @"aseruy56uiytitfesh";
itemTitle.adjustsFontSizeToFitWidth = NO;
itemTitle.autoresizingMask = UIViewAutoresizingFlexibleWidth;
itemTitle.font = [UIFont boldSystemFontOfSize:18.0];
itemTitle.textColor = [UIColor blackColor];
itemTitle.shadowColor = [UIColor whiteColor];
itemTitle.shadowOffset = CGSizeMake(0, 1);
itemTitle.backgroundColor = [UIColor blueColor];
itemTitle.lineBreakMode = UILineBreakModeWordWrap;
itemTitle.numberOfLines = 0;
[itemTitle sizeToFit];
[self.view addSubview:itemTitle];
используйте здесь все свойства, используемые на метке, и проверьте это, увеличив текст в itemTitle.text как
itemTitle.text = @"diofgorigjveghnhkvjteinughntivugenvitugnvkejrfgnvkhv";
он покажет ответ perfetc, как вам нужно
Спасибо за этот пост. Это мне очень помогло. В моем случае я также редактирую текст в отдельном контроллере представления. Я заметил, что когда я использую:
[cell.contentView addSubview:cellLabel];
в tableView:cellForRowAtIndexPath: метод, чтобы представление метки постоянно отображалось поверх предыдущего представления каждый раз, когда я редактировал ячейку. Текст стал пикселированным, и когда что-то было удалено или изменено, предыдущая версия была видна под новой версией. Вот как я решил проблему:
if ([[cell.contentView subviews] count] > 0) {
UIView *test = [[cell.contentView subviews] objectAtIndex:0];
[test removeFromSuperview];
}
[cell.contentView insertSubview:cellLabel atIndex:0];
Нет больше странных слоев. Если есть лучший способ справиться с этим, пожалуйста, дайте мне знать.
Вы также можете использовать его как метод. @Pyjamasam очень верный, поэтому я просто делаю его метод. Это может быть полезно для кого-то еще
-(CGRect)setDynamicHeightForLabel:(UILabel*)_lbl andMaxWidth:(float)_width{
CGSize maximumLabelSize = CGSizeMake(_width, FLT_MAX);
CGSize expectedLabelSize = [_lbl.text sizeWithFont:_lbl.font constrainedToSize:maximumLabelSize lineBreakMode:_lbl.lineBreakMode];
//adjust the label the the new height.
CGRect newFrame = _lbl.frame;
newFrame.size.height = expectedLabelSize.height;
return newFrame;
}
и просто установите это так
label.frame = [self setDynamicHeightForLabel:label andMaxWidth:300.0];
Наконец-то это сработало. Спасибо вам, ребята.
Я не получал его на работу, потому что я пытался изменить размер лейбла в heightForRowAtIndexPath
метод:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
и (да, глупый я), я изменил размер этикетки по умолчанию в cellForRowAtIndexPath
Метод - я пропускал код, который написал ранее:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
NSString *str = @"Please enter your text......";
CGSize lblSize = [str sizeWithFont:[UIFont systemFontOfSize:15] constrainedToSize: CGSizeMake(200.0f, 600.0f) lineBreakMode: NSLineBreakByWordWrapping];
UILabel *label = [[UILabel alloc]init];
label.frame = CGRectMake(60, 20, 200, lblSize.height);
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.font = [UIFont systemFontOfSize:15];
label.text = str;
label.backgroundColor = [UIColor clearColor];
[label sizeToFit];
[self.view addSubview:label];
myLabel.text = "your very long text"
myLabel.numberOfLines = 0
myLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
Пожалуйста, установите ограничения для UILable в раскадровке, включая верхний левый нижний правый
Мой код:
UILabel *label = [[UILabel alloc] init];
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.text = text;
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont fontWithName:_bodyTextFontFamily size:_bodyFontSize];
CGSize size = [label sizeThatFits:CGSizeMake(width, MAXFLOAT)];
float height = size.height;
label.frame = CGRectMake(x, y, width, height);
Одна строка Криса ответ неверен.
newFrame.size.height = maximumLabelSize.height;
должно быть
newFrame.size.height = expectedLabelSize.height;
Кроме этого, это правильное решение.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cellIdentifier = @"myCell";
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.myUILabel.lineBreakMode = UILineBreakModeWordWrap;
cell.myUILabel.numberOfLines = 0;
cell.myUILabel.text = @"Some very very very very long text....."
[cell.myUILabel.criterionDescriptionLabel sizeToFit];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
CGFloat rowHeight = cell.myUILabel.frame.size.height + 10;
return rowHeight;
}
Этот метод даст идеальную высоту
-(float) getHeightForText:(NSString*) text withFont:(UIFont*) font andWidth:(float) width{
CGSize constraint = CGSizeMake(width , 20000.0f);
CGSize title_size;
float totalHeight;
title_size = [text boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{ NSFontAttributeName : font }
context:nil].size;
totalHeight = ceil(title_size.height);
CGFloat height = MAX(totalHeight, 40.0f);
return height;
}