Trong iOS 7, sizeWithFont:
hiện không dùng nữa. Làm thế nào để bây giờ tôi chuyển đối tượng UIFont vào phương thức thay thế sizeWithAttributes:
?
Trong iOS 7, sizeWithFont:
hiện không dùng nữa. Làm thế nào để bây giờ tôi chuyển đối tượng UIFont vào phương thức thay thế sizeWithAttributes:
?
Câu trả lời:
Sử dụng sizeWithAttributes:
thay thế, mà bây giờ mất một NSDictionary
. Chuyển qua cặp với khóa UITextAttributeFont
và đối tượng phông chữ của bạn như thế này:
CGSize size = [string sizeWithAttributes:
@{NSFontAttributeName: [UIFont systemFontOfSize:17.0f]}];
// Values are fractional -- you should take the ceilf to get equivalent values
CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));
boundingRectWithSize:options:attributes:context:
thay thế, CGSizeMake(250.0f, CGFLOAT_MAX)
trong hầu hết các trường hợp.
Tôi tin rằng chức năng này không được chấp nhận vì một loạt các NSString+UIKit
chức năng ( sizewithFont:...
, v.v.) được dựa trên UIStringDrawing
thư viện, không an toàn cho chuỗi. Nếu bạn đã cố chạy chúng không phải trên luồng chính (như mọi UIKit
chức năng khác ), bạn sẽ có những hành vi không thể đoán trước. Cụ thể, nếu bạn chạy chức năng trên nhiều luồng cùng một lúc, nó có thể sẽ làm hỏng ứng dụng của bạn. Đây là lý do tại sao trong iOS 6, họ đã giới thiệu một boundingRectWithSize:...
phương pháp cho NSAttributedString
. Điều này đã được xây dựng trên đầu các NSStringDrawing
thư viện và là chủ đề an toàn.
Nếu bạn nhìn vào NSString
boundingRectWithSize:...
hàm mới , nó sẽ yêu cầu một mảng thuộc tính theo cách tương tự như a NSAttributeString
. Nếu tôi phải đoán, NSString
chức năng mới này trong iOS 7 chỉ đơn thuần là một trình bao bọc cho NSAttributeString
chức năng từ iOS 6.
Trên lưu ý đó, nếu bạn chỉ hỗ trợ iOS 6 và iOS 7, thì tôi chắc chắn sẽ thay đổi tất cả của bạn NSString
sizeWithFont:...
thành NSAttributeString
boundingRectWithSize
. Nó sẽ giúp bạn đỡ đau đầu hơn nếu bạn có một trường hợp góc đa luồng kỳ lạ! Đây là cách tôi chuyển đổi NSString
sizeWithFont:constrainedToSize:
:
Những gì đã từng là:
NSString *text = ...;
CGFloat width = ...;
UIFont *font = ...;
CGSize size = [text sizeWithFont:font
constrainedToSize:(CGSize){width, CGFLOAT_MAX}];
Có thể được thay thế bằng:
NSString *text = ...;
CGFloat width = ...;
UIFont *font = ...;
NSAttributedString *attributedText =
[[NSAttributedString alloc] initWithString:text
attributes:@{NSFontAttributeName: font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize size = rect.size;
Xin lưu ý các tài liệu đề cập:
Trong iOS 7 trở lên, phương thức này trả về kích thước phân đoạn (trong thành phần kích thước được trả về
CGRect
); để sử dụng kích thước được trả về cho chế độ xem kích thước, bạn phải sử dụng nâng giá trị của nó lên số nguyên cao hơn gần nhất bằng hàm trần.
Vì vậy, để kéo ra chiều cao hoặc chiều rộng được tính toán được sử dụng để định cỡ khung nhìn, tôi sẽ sử dụng:
CGFloat height = ceilf(size.height);
CGFloat width = ceilf(size.width);
Như bạn có thể thấy sizeWithFont
tại trang web Apple Developer, nó không được dùng nữa nên chúng tôi cần sử dụng sizeWithAttributes
.
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
NSString *text = @"Hello iOS 7.0";
if (SYSTEM_VERSION_LESS_THAN(@"7.0")) {
// code here for iOS 5.0,6.0 and so on
CGSize fontSize = [text sizeWithFont:[UIFont fontWithName:@"Helvetica"
size:12]];
} else {
// code here for iOS 7.0
CGSize fontSize = [text sizeWithAttributes:
@{NSFontAttributeName:
[UIFont fontWithName:@"Helvetica" size:12]}];
}
[NSObject respondsToSelector:]
phương pháp như ở đây: stackoverflow.com/a/3863039/1226304
Tôi đã tạo một danh mục để xử lý vấn đề này, đây là:
#import "NSString+StringSizeWithFont.h"
@implementation NSString (StringSizeWithFont)
- (CGSize) sizeWithMyFont:(UIFont *)fontToUse
{
if ([self respondsToSelector:@selector(sizeWithAttributes:)])
{
NSDictionary* attribs = @{NSFontAttributeName:fontToUse};
return ([self sizeWithAttributes:attribs]);
}
return ([self sizeWithFont:fontToUse]);
}
Bằng cách này, bạn chỉ cần tìm / thay thế sizeWithFont:
với sizeWithMyFont:
và bạn tốt để đi.
Trong iOS7, tôi cần logic để trả về chiều cao chính xác cho chế độ xem bảng: phương thức heightForRowAtIndexPath, nhưng sizeWithAttribution luôn trả về cùng một chiều cao bất kể độ dài chuỗi vì nó không biết rằng nó sẽ được đặt trong một ô bảng có chiều rộng cố định . Tôi thấy điều này rất tốt cho tôi và tính toán chiều cao chính xác khi xem xét chiều rộng cho ô của bảng! Điều này dựa trên câu trả lời của ông T ở trên.
NSString *text = @"The text that I want to wrap in a table cell."
CGFloat width = tableView.frame.size.width - 15 - 30 - 15; //tableView width - left border width - accessory indicator - right border width
UIFont *font = [UIFont systemFontOfSize:17];
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:@{NSFontAttributeName: font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize size = rect.size;
size.height = ceilf(size.height);
size.width = ceilf(size.width);
return size.height + 15; //Add a little more padding for big thumbs and the detailText label
Nhãn nhiều dòng sử dụng chiều cao động có thể yêu cầu thông tin bổ sung để đặt kích thước chính xác. Bạn có thể sử dụng sizeWithAttribution với UIFont và NSPar ĐoạnStyle để chỉ định cả phông chữ và chế độ ngắt dòng.
Bạn sẽ xác định Kiểu đoạn văn và sử dụng một NSDipedia như thế này:
// set paragraph style
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setLineBreakMode:NSLineBreakByWordWrapping];
// make dictionary of attributes with paragraph style
NSDictionary *sizeAttributes = @{NSFontAttributeName:myLabel.font, NSParagraphStyleAttributeName: style};
// get the CGSize
CGSize adjustedSize = CGSizeMake(label.frame.size.width, CGFLOAT_MAX);
// alternatively you can also get a CGRect to determine height
CGRect rect = [myLabel.text boundingRectWithSize:adjustedSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:sizeAttributes
context:nil];
Bạn có thể sử dụng thuộc tính CGSize 'điều chỉnh kích thước' hoặc CGRect làm thuộc tính orth.size.height nếu bạn đang tìm kiếm chiều cao.
Thông tin thêm về NSPar ĐoạnStyle tại đây: https://developer.apple.com/l Library / mac / document / cocoa / refference / applicationkit / classes / NSPar ĐoạnStyle_Class / Reference / Reference.html
// max size constraint
CGSize maximumLabelSize = CGSizeMake(184, FLT_MAX)
// font
UIFont *font = [UIFont fontWithName:TRADE_GOTHIC_REGULAR size:20.0f];
// set paragraph style
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
// dictionary of attributes
NSDictionary *attributes = @{NSFontAttributeName:font,
NSParagraphStyleAttributeName: paragraphStyle.copy};
CGRect textRect = [string boundingRectWithSize: maximumLabelSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
CGSize expectedLabelSize = CGSizeMake(ceil(textRect.size.width), ceil(textRect.size.height));
Tạo một hàm lấy một ví dụ UILabel. và trả về CGSize
CGSize constraint = CGSizeMake(label.frame.size.width , 2000.0);
// Adjust according to requirement
CGSize size;
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0){
NSRange range = NSMakeRange(0, [label.attributedText length]);
NSDictionary *attributes = [label.attributedText attributesAtIndex:0 effectiveRange:&range];
CGSize boundingBox = [label.text boundingRectWithSize:constraint options: NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size;
size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));
}
else{
size = [label.text sizeWithFont:label.font constrainedToSize:constraint lineBreakMode:label.lineBreakMode];
}
return size;
tableView.estimatedRowHeight = 68.0 tableView.rowHeight = UITableViewAutomaticDimension
Giải pháp thay thế-
CGSize expectedLabelSize;
if ([subTitle respondsToSelector:@selector(sizeWithAttributes:)])
{
expectedLabelSize = [subTitle sizeWithAttributes:@{NSFontAttributeName:subTitleLabel.font}];
}else{
expectedLabelSize = [subTitle sizeWithFont:subTitleLabel.font constrainedToSize:subTitleLabel.frame.size lineBreakMode:NSLineBreakByWordWrapping];
}
Dựa trên @bitsand, đây là một phương pháp mới tôi vừa thêm vào danh mục NSString + Extras của mình:
- (CGRect) boundingRectWithFont:(UIFont *) font constrainedToSize:(CGSize) constraintSize lineBreakMode:(NSLineBreakMode) lineBreakMode;
{
// set paragraph style
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setLineBreakMode:lineBreakMode];
// make dictionary of attributes with paragraph style
NSDictionary *sizeAttributes = @{NSFontAttributeName:font, NSParagraphStyleAttributeName: style};
CGRect frame = [self boundingRectWithSize:constraintSize options:NSStringDrawingUsesLineFragmentOrigin attributes:sizeAttributes context:nil];
/*
// OLD
CGSize stringSize = [self sizeWithFont:font
constrainedToSize:constraintSize
lineBreakMode:lineBreakMode];
// OLD
*/
return frame;
}
Tôi chỉ sử dụng kích thước của khung kết quả.
Bạn vẫn có thể sử dụng sizeWithFont
. nhưng, trong phương thức iOS> = 7.0 gây ra sự cố nếu chuỗi chứa khoảng trắng ở đầu và cuối hoặc cuối dòng \n
.
Cắt bớt văn bản trước khi sử dụng nó
label.text = [label.text stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
Điều đó cũng có thể áp dụng cho sizeWithAttributes
và [label sizeToFit]
.
Ngoài ra, bất cứ khi nào bạn có nsstringdrawingtextstorage message sent to deallocated instance
trong thiết bị iOS 7.0, nó sẽ xử lý vấn đề này.
Sử dụng tốt hơn kích thước tự động (Swift):
tableView.estimatedRowHeight = 68.0
tableView.rowHeight = UITableViewAutomaticDimension
Lưu ý
VIDEO: https://youtu.be/Sz3XfCsSb6k
Câu trả lời được chấp nhận trong Xamarin sẽ là (sử dụng sizeWithAttribut và UITextAttributionFont):
UIStringAttributes attributes = new UIStringAttributes
{
Font = UIFont.SystemFontOfSize(17)
};
var size = text.GetSizeUsingAttributes(attributes);
Như câu trả lời @Ayush:
Như bạn có thể thấy
sizeWithFont
tại trang web Apple Developer, nó không được dùng nữa nên chúng tôi cần sử dụngsizeWithAttributes
.
Chà, giả sử rằng vào năm 2019+, có lẽ bạn đang sử dụng Swift và String
thay vì Objective-c và NSString
, đây là cách chính xác để có được kích thước của một String
phông chữ được xác định trước:
let stringSize = NSString(string: label.text!).size(withAttributes: [.font : UIFont(name: "OpenSans-Regular", size: 15)!])
- (CGSize) sizeWithMyFont:(UIFont *)fontToUse
{
if ([self respondsToSelector:@selector(sizeWithAttributes:)])
{
NSDictionary* attribs = @{NSFontAttributeName:fontToUse};
return ([self sizeWithAttributes:attribs]);
}
return ([self sizeWithFont:fontToUse]);
}
Đây là tương đương monotouch nếu bất cứ ai cần nó:
/// <summary>
/// Measures the height of the string for the given width.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="font">The font.</param>
/// <param name="width">The width.</param>
/// <param name="padding">The padding.</param>
/// <returns></returns>
public static float MeasureStringHeightForWidth(this string text, UIFont font, float width, float padding = 20)
{
NSAttributedString attributedString = new NSAttributedString(text, new UIStringAttributes() { Font = font });
RectangleF rect = attributedString.GetBoundingRect(new SizeF(width, float.MaxValue), NSStringDrawingOptions.UsesLineFragmentOrigin, null);
return rect.Height + padding;
}
có thể được sử dụng như thế này:
public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
//Elements is a string array
return Elements[indexPath.Row].MeasureStringHeightForWidth(UIFont.SystemFontOfSize(UIFont.LabelFontSize), tableView.Frame.Size.Width - 15 - 30 - 15);
}
CGSize maximumLabelSize = CGSizeMake(label.frame.size.width, FLT_MAX);
CGSize expectedLabelSize = [label sizeThatFits:maximumLabelSize];
float heightUse = expectedLabelSize.height;
Hãy thử cú pháp này:
NSAttributedString *attributedText =
[[NSAttributedString alloc] initWithString:text
attributes:@{NSFontAttributeName: font}];
Không ai trong số này làm việc cho tôi trong ios 7. Đây là những gì tôi đã làm. Tôi đặt cái này trong lớp ô tùy chỉnh của mình và gọi phương thức trong phương thức heightForCellAtIndexPath của tôi.
Ô của tôi trông giống với ô mô tả khi xem một ứng dụng trong cửa hàng ứng dụng.
Đầu tiên trong bảng phân cảnh, hãy đặt nhãn của bạn thành 'AttTextText', đặt số lượng dòng thành 0 (sẽ tự động thay đổi kích thước nhãn (chỉ ios 6+)) và đặt nó thành bao bọc từ.
Sau đó, tôi chỉ cần cộng tất cả các độ cao của nội dung của ô trong Lớp ô tùy chỉnh của mình. Trong trường hợp của tôi, tôi có một Nhãn ở đầu luôn ghi "Mô tả" (_descripHeadLabel), một nhãn nhỏ hơn có kích thước thay đổi có chứa mô tả thực tế (_descripLabel) một ràng buộc từ đầu ô đến tiêu đề (_descripHeadLabelTopConstraint) . Tôi cũng đã thêm 3 vào khoảng trống phía dưới một chút (khoảng cùng một số vị trí táo trên ô loại phụ đề.)
- (CGFloat)calculateHeight
{
CGFloat width = _descriptionLabel.frame.size.width;
NSAttributedString *attributedText = _descriptionLabel.attributedText;
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX} options: NSStringDrawingUsesLineFragmentOrigin context:nil];
return rect.size.height + _descriptionHeadingLabel.frame.size.height + _descriptionHeadingLabelTopConstraint.constant + 3;
}
Và trong đại biểu Bảng xem của tôi:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
if (indexPath.row == 0) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"descriptionCell"];
DescriptionCell *descriptionCell = (DescriptionCell *)cell;
NSString *text = [_event objectForKey:@"description"];
descriptionCell.descriptionLabel.text = text;
return [descriptionCell calculateHeight];
}
return 44.0f;
}
Bạn có thể thay đổi câu lệnh if trở nên 'thông minh hơn' một chút và thực sự lấy mã định danh ô từ một số nguồn dữ liệu. Trong trường hợp của tôi, các ô sẽ được mã hóa cứng vì sẽ có số lượng cố định của chúng theo một thứ tự cụ thể.
boundingRectWithSize
trong ios 9.2 có vấn đề, là kết quả khác với ios <9.2. Bạn tìm thấy hoặc biết bất kỳ cách tốt nhất khác để thực hiện điều này.
NSString
và mộtUILabel
(không phải LUÔN LUÔN, nhưng thường là như vậy), để ngăn chặn mã trùng lặp / etc, bạn cũng có thể thay thế[UIFont systemFontOfSize:17.0f]
bằnglabel.font
- giúp bảo trì mã bằng cách tham chiếu dữ liệu hiện có so với việc bạn nhập nhiều lần hoặc tham chiếu các hằng số trên tất cả địa điểm, v.v.