Phương thức sizeWithFont không được dùng nữa. bindingRectWithSize trả về một giá trị không mong đợi


82

Trong iOS7, sizeWithFontkhông được dùng nữa, vì vậy tôi đang sử dụng boundingRectWithSize(trả về giá trị CGRect). Mã của tôi:

 UIFont *fontText = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16];
                    // you can use your font.

 CGSize maximumLabelSize = CGSizeMake(310, 9999);

 CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                             options:NSStringDrawingUsesLineFragmentOrigin
                             attributes:@{NSFontAttributeName:fontText}
                             context:nil];

 expectedLabelSize = CGSizeMake(textRect.size.width, textRect.size.height);

Trong textRect, tôi nhận được một kích thước lớn hơn của tôi maximumLabelSize, một kích thước khác với khi sử dụng sizeWithFont. Tôi có thể giải quyết vấn đề này bằng cách nào?


Tôi gặp sự cố này với tất cả các phông chữ không chỉ phông chữ hệ thống hoặc Helvetica.
Nirav Jain

bạn có bất kỳ ý tưởng làm thế nào để làm điều đó?
Nirav Jain

Ví dụ cụ thể về tên phông chữ, văn bản và kích thước không khớp có thể hữu ích.
Eiko

Tôi đã từng sử dụng CTFramesetterSuggestFrameSizeWithConstraints trong iOS6 để tính toán chiều cao của chuỗi thuộc tính luôn trả về chiều cao chính xác. Trong iOS7, cả CTFramesetterSuggestFrameSizeWithConstraints và bindingRectWithSize đều cho tôi kết quả chiều cao sai. Tôi cá rằng đó là một lỗi được giới thiệu trong iOS7 và có vẻ như vẫn chưa có giải pháp.
Arnold Tang

Tôi cũng đang đối mặt với vấn đề tương tự, tốt hơn là sử dụng tttattributedlabel
Sri ..

Câu trả lời:


151

Làm thế nào về tạo nhãn mới và sử dụng sizeThatFit:(CGSize)size??

UILabel *gettingSizeLabel = [[UILabel alloc] init];
gettingSizeLabel.font = [UIFont fontWithName:@"YOUR FONT's NAME" size:16];
gettingSizeLabel.text = @"YOUR LABEL's TEXT";
gettingSizeLabel.numberOfLines = 0;
gettingSizeLabel.lineBreakMode = NSLineBreakByWordWrapping;
CGSize maximumLabelSize = CGSizeMake(310, CGFLOAT_MAX);

CGSize expectSize = [gettingSizeLabel sizeThatFits:maximumLabelSize];

Chỉnh sửa: Mã phía trên này không tốt cho iOS 7 trở lên, vì vậy hãy sử dụng bên dưới:

CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                         options:NSStringDrawingUsesLineFragmentOrigin| NSStringDrawingUsesFontLeading
                         attributes:@{NSFontAttributeName:fontText}
                         context:nil];

phương pháp này không hoạt động khi tôi thêm các thực thể HTML như (<OL>, <LI>) trong chuỗi.
Nirav Jain

vui lòng kiểm tra lại câu trả lời của tôi! Tôi đã bỏ lỡ tài sản numberOfLines! lấy làm tiếc!
Quang Hà

1
Sau hàng giờ đồng hồ tìm kiếm, thử nghiệm và kết thúc, đây là giải pháp duy nhất hoạt động cho iOS7 và Xamarin / Monotouch
Michael Rodrigues

26
Tạo nhãn để tính toán kích thước cho phông chữ? Thật là lãng phí!
Ossir

13
@Ossir, bạn có ý tưởng nào hay hơn không?
Luda

36

Có thể bạn cần cung cấp tùy chọn bổ sung cho phương pháp được đề xuất trong câu trả lời này :

CGSize maximumLabelSize = CGSizeMake(310, CGFLOAT_MAX);
CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                                         options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                      attributes:@{NSFontAttributeName: fontText}
                                         context:nil];

3
Có vẻ như boundingRectWithSizebị hỏng. Tôi đã thử nghiệm trên iOS 7, 7.1.1 và nó trả về kết quả không chính xác.
RaffAl,

Điều này không hiệu quả với tôi, tuy nhiên, việc sử dụng bindingRectWithSize trên NSAttributedString và thêm thuộc tính phông chữ của tôi vào chuỗi đã hoạt động.
Sheepdogsheep

12
Các bạn, đừng quên tuyên bố của Apple: Trong iOS 7 trở lên, phương thức này trả về kích thước phân số (trong thành phần kích thước của CGRect được trả về); để sử dụng kích thước được trả về cho các 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 cách sử dụng hàm ceil.
SoftDesigner

2
ceil là không đủ đối với tôi, nhưng thấy rằng việc sử dụng ceil và cũng thêm 0,5 đã làm các trick
dwery

15

Đây là đoạn mã làm việc của tôi:

NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:attributeDict];

NSString *headline  = [dict objectForKey:@"title"];  
UIFont *font        = [UIFont boldSystemFontOfSize:18];  
CGRect  rect        = [headline boundingRectWithSize:CGSizeMake(300, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];

CGFloat height      = roundf(rect.size.height +4)

Tôi đã thêm 4px vào chiều cao được tính toán, bởi vì nếu không có 4px này, sẽ thiếu một dòng.

Tôi sử dụng đoạn mã này trong tableView và thêm "height" vào một mảng NSNumbers và tôi nhận được chiều cao ô chính xác cho textLabel mặc định.

Thêm 4 pixel nữa nếu bạn muốn có thêm không gian bên dưới văn bản trong textLabel.

**** CẬP NHẬT ****

Tôi không đồng ý với "lỗi chiều rộng của 40px", tôi gọi là 4px chiều cao bị thiếu, bởi vì 4px là chiều cao mặc định của khoảng cách giữa một chữ cái và giới hạn của một dòng. Bạn có thể kiểm tra nó bằng UILabel, đối với kích thước phông chữ là 16, bạn cần chiều cao UILabel là 20.

Nhưng nếu dòng cuối cùng của bạn không có chữ "g" hoặc bất cứ thứ gì trong đó, thì số đo có thể bị sai 4px chiều cao.

Tôi đã kiểm tra lại nó bằng một phương pháp nhỏ, tôi nhận được chiều cao chính xác là 20,40 hoặc 60 cho nhãn của mình và chiều rộng bên phải nhỏ hơn 300px.

Để hỗ trợ iOS6 và iOS7, bạn có thể sử dụng phương pháp của tôi:

- (CGFloat)heightFromString:(NSString*)text withFont:(UIFont*)font constraintToWidth:(CGFloat)width
{
    CGRect rect;

    float iosVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (iosVersion >= 7.0) {
        rect = [text boundingRectWithSize:CGSizeMake(width, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];
    }
    else {
        CGSize size = [text sizeWithFont:font constrainedToSize:CGSizeMake(width, 1000) lineBreakMode:NSLineBreakByWordWrapping];
        rect = CGRectMake(0, 0, size.width, size.height);
    }
    NSLog(@"%@: W: %.f, H: %.f", self, rect.size.width, rect.size.height);
    return rect.size.height;
}

**** NÂNG CẤP ****

Nhờ ý kiến ​​của bạn, tôi đã nâng cấp chức năng của mình như sau. Vì sizeWithFont không được dùng nữa và bạn sẽ nhận được cảnh báo trong XCode, nên tôi đã thêm mã chẩn đoán-pragma-code để xóa cảnh báo cho lệnh gọi / khối mã cụ thể này.

- (CGFloat)heightFromStringWithFont:(UIFont*)font constraintToWidth:(CGFloat)width
{
    CGRect rect;

    if ([self respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
        rect = [self boundingRectWithSize:CGSizeMake(width, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];
    }
    else {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
        CGSize size = [self sizeWithFont:font constrainedToSize:CGSizeMake(width, 1000) lineBreakMode:NSLineBreakByWordWrapping];
        rect = CGRectMake(0, 0, size.width, size.height);
#pragma GCC diagnostic pop
    }
    return ceil(rect.size.height);
}

Ngoài chủ đề 4px: tùy thuộc vào phông chữ và trọng lượng phông chữ bạn sử dụng, phép tính trả về các giá trị chiều cao khác nhau. Trong trường hợp của tôi: HelveticaNeue-Medium với kích thước phông chữ là 16.0 trả về chiều cao dòng là 20.0 cho một dòng nhưng 39.0 cho hai dòng, 78px cho 4 dòng -> thiếu 1px cho mọi dòng - bắt đầu bằng dòng 2 - nhưng bạn muốn để có kích thước phông chữ + không gian dòng 4px cho mỗi dòng, bạn phải lấy kết quả chiều cao.
Hãy ghi nhớ điều đó trong khi viết mã!
Tôi chưa có một chức năng nào cho "sự cố" này nhưng tôi sẽ cập nhật bài đăng này khi tôi hoàn thành.


1
Có lẽ bạn nên sử dụng [text responseToSelector: @selector (bindingRectWithSize: options: thuộc tính: context :)] thay vì kiểm tra một giá trị float.
Samah

1
Tốt hơn nên sử dụng hàm ceil thay vì + 4pt, hãy xem câu trả lời này stackoverflow.com/a/23563152/667483
lướt sóng

2

Nếu tôi hiểu đúng, bạn đang sử dụng bindingRectWithSize: giống như một cách để lấy kích thước bạn sẽ nhận được với sizeWithFont (nghĩa là bạn muốn trực tiếp CGSize, không phải CGRect)?

Điều này giống như những gì bạn đang tìm kiếm:

Thay thế cho kích thước không dùng nữaWithFont: trong iOS 7?

Họ đang sử dụng sizeWithAttributes: để lấy kích thước, thay thế cho sizeWithFont.

Bạn vẫn nhận được kích thước sai khi sử dụng một cái gì đó như thế này:

UIFont *fontText = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16];
                    // you can use your font.

expectedLabelSize = [myString sizeWithAttributes:@{NSFontAttributeName:fontText}];

nhưng làm thế nào tôi có thể sử dụng CGSize MaximumLabelSize = CGSizeMake (310, 9999)? Tôi cần chiều cao và chiều rộng chính xác.
Nirav Jain,

1
Có thuộc tính nào cho biết sizeWithAttributes: hạn chế chiều rộng / chiều cao của nó không?
Nirav Jain

Xin lỗi, nhưng tôi không hiểu vấn đề của bạn là gì. Bạn muốn định kích thước nhãn với kích thước phông chữ, nhưng không lớn hơn chiều cao tối đa, nếu tôi hiểu chính xác. Bạn nói rằng bạn có thể làm điều đó với sizeWithFont, nhưng bạn muốn một giải pháp thay thế hiện tại phương pháp này không được dùng nữa, đúng không? Bạn sẽ có thể cắm sizeWithAttribues: giống như cách bạn đang sử dụng sizeWithFont :. Bạn đã hạn chế kích thước nhãn như thế nào khi sử dụng sizeWithFont? Bạn có thể đăng mã đang hoạt động cho bạn bằng cách sử dụng sizeWithFont không?
vinaut

2
Anh ta đang sử dụng sizeWithFont: bindinedToSize: lineBreakMode: và không có cách nào để chuyển giá trị bindinedToSize thành sizeWithAttributes.
zh.

2

Nhận xét của @ SoftDesigner đã phù hợp với tôi

CGRect descriptionRect = [description boundingRectWithSize:CGSizeMake(width, 0)
                                                       options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                                    attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:12]}
                                                       context:nil];
result = ceil(descriptionRect.size.height);

1

để tìm kích thước của thời gian chạy nhãn sizewithfont không được dùng cho iOS 7.0 thay vào đó bạn phải sử dụng -boundRectWithSize: options: thuộc tính: context: method

bạn có thể sử dụng nó như mã dưới đây

CGSize constraint = CGSizeMake(MAXIMUM_WIDHT, TEMP_HEIGHT);
NSRange range = NSMakeRange(0, [[self.message body] length]);

NSDictionary *attributes = [YOUR_LABEL.attributedText attributesAtIndex:0 effectiveRange:&range];
CGSize boundingBox = [myString boundingRectWithSize:constraint options:NSStringDrawingUsesFontLeading attributes:attributes context:nil].size;
int numberOfLine = ceil((boundingBox.width) / YOUR_LABEL.frame.size.width);
CGSize descSize = CGSizeMake(ceil(boundingBox.width), ceil(self.lblMessageDetail.frame.size.height*numberOfLine));

CGRect frame=YOUR_LABEL.frame;
frame.size.height=descSize.height;
YOUR_LABEL.frame=frame;

ở đây bạn phải cung cấp chiều rộng cho chiều dài tối đa để tìm chiều cao hoặc chiều rộng.

hãy thử điều này nó đang làm việc cho tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.