2010-02-25 28 views
15

Có cách nào để có được kích thước chính xác của một NSString sử dụng:sizeWithFont không cho chiều cao chính xác cho UITextView nếu có một chuỗi dài trong văn bản được bọc

- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode 

rằng doesnt được ném ra bởi 2 hoặc 3 trăm chuỗi ký tự. Tại thời điểm này nếu tôi cố gắng sử dụng phương pháp này trên các chuỗi dài, nó tính toán không chính xác chúng và tôi kết thúc với rất nhiều khoảng trống ở dưới cùng của UITextView.

Tôi đã thử sử dụng UILineBreakModeWordWrap và UILineBreakModeCharacterWrap.

thay đổi kích thước đang được thực hiện trong

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    CGFloat  result = 44.0f; 
    NSString* text = nil; 
    CGFloat  width = 0; 
    CGFloat  tableViewWidth; 
    CGRect  bounds = [UIScreen mainScreen].bounds; 

    tableViewWidth = bounds.size.width; 


    width = tableViewWidth - 150;  

    text = stringWithLongWords; 

    if (text) { 
     CGSize  textSize = { width, 20000.0f };  
     CGSize  size = [text sizeWithFont:[UIFont systemFontOfSize:10.0f] constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap]; 

     size.height += 50.0f;    
     result = MAX(size.height, 44.0f+30.0f); 
    } 

    return result; 
} 
+0

biết chính xác là bạn đang cố gắng để làm gì? Tôi nghĩ sizeWithFont: hoạt động khá tốt, có thể đó là cách bạn áp dụng thông tin đó cho UITextView. Vui lòng giải thích. –

+0

Tôi có một ô UITableView tùy chỉnh có 2 UILabels và UITextView sử dụng sizeWithFont để tính toán kích thước cần thiết cho chiều cao ô và ô ở các thời điểm kết thúc lên trên 400 pixel quá cao. –

Trả lời

1

Bạn nói rằng bạn có một UITableView với chiều cao khác nhau. Bạn đã đặt định danh tái sử dụng cho cùng một thứ cho tất cả các ô? Nó có thể là các tế bào cũ với chiều cao của chúng đã được thiết lập đang được tái sử dụng. Nếu đây là vấn đề, bạn nên thay đổi kích thước các tế bào một lần nữa khi nó đang được tái sử dụng.

+0

Chỉ có một ô thuộc loại này trên UITableView, tôi đã kiểm tra xem đây có phải là một vấn đề hay không. –

21

UITextView không chính xác giống như UILabel được bọc trong UIScrollView. Nó có khoảng cách dòng khác với kích thước phông chữ và lề mà sizeWithFont:constrainedToSize:linkBreakMode: không tính đến.

Biết kích thước phông chữ của bạn, bạn có thể tính toán số dòng và tính khoảng cách dòng. Bạn có thể đoán tại các lề và cố gắng để lừa sizeWithFont: để cung cấp cho một câu trả lời hữu ích hơn.

Các giải pháp phổ biến dường như là:

  • chỉ cần sử dụng một UILabel nếu bạn không cần bất kỳ chức năng UITextView

  • nếu bạn cần hyperlinks, lớp phủ UIButtons trông giống như các siêu liên kết trong một UILabel

  • sử dụng một màn hình ngoài UITextView và phương thức sizeToFit để nhận khoản tiền thật wer

Tôi không có may mắn với tùy chọn thứ 3 nhưng có vẻ như nó sẽ hoạt động, vì vậy có lẽ tôi đã làm điều gì sai.

Tôi sẽ thử sử dụng các nút UILabel và lớp phủ cho siêu liên kết. Chúng ta sẽ thấy điều đó hóa ra thế nào.

Nếu không thành công, luôn có tùy chọn được thực hiện bởi Loren Brichter (của Tweetie fame): vẽ mọi thứ vào một số UIView bằng cách sử dụng CoreGraphics.

Chúc may mắn!

+2

Tùy chọn thứ ba có thể không hoạt động vì sizeToFit sẽ không hoạt động cho đến khi UITextView được hiển thị trên màn hình. Chỉ là một ý nghĩ. – Quentamia

+0

Thú vị. Tôi tự hỏi nếu bạn có thể làm cho nó trên màn hình nhưng với alpha = 0 hoặc một cái gì đó rất thấp để lừa nó vào rendering nhưng vẫn không nhìn thấy được cho mắt người. –

+0

Điều đó có thể hoạt động và sẽ là một thử nghiệm thú vị. Tôi rất muốn tìm một cách để tính toán chính xác chiều cao trước khi dựng hình. Nó sẽ rất hữu ích khi UITextViews được sử dụng trong UITableViewCells. – Quentamia

9

Check-out bài này How do I size a UITextView to its content?

Dường như textView.contentSize.height nên làm việc (với sự báo trước rằng các contentSize đúng là chỉ có sẵn sau khi UITextView đã được thêm vào vùng đang xem với addSubview)

1

Giải pháp tốt nhất mà tôi đã tìm thấy cho đến nay là có một UITextView ẩn riêng biệt với cùng một cài đặt phông chữ và đặt văn bản của nó.Sau đó contetSize của nó phải chính xác.

0

Lấy cảm hứng từ câu trả lời @ MrNickBarker của, đây là giải pháp của tôi:

CGFloat width = 280.0f; 

UITextView *t = [[UITextView alloc] init]; 
[t setFont:[UIFont systemFontOfSize:17]]; 
[label setText:@"some short or long text, works both"]; 

CGRect frame = CGRectMake(0, 0, width, 0); 
[t setFrame:frame]; 
// Here's the trick: after applying the 0-frame, the content size is calculated and can be used in a second invocation 
frame = CGRectMake(0, 0, width, t.contentSize.height); 
[t setFrame:frame]; 

Vấn đề duy nhất còn lại đối với tôi là điều này không làm việc với insets sửa đổi. Tuy nhiên, không thể tin rằng các xoắn đó là bắt buộc, nhưng vì -[NSString sizeWithFont:forWidth:lineBreakMode:] không tôn trọng insets, paddings, margins, line spacings và các loại tương tự, có vẻ như đây là giải pháp làm việc duy nhất vào lúc này (ví dụ: iOS 6).

1

Chiều rộng bạn đang sử dụng là chiều rộng cho UITextView của bạn ... nhưng bạn không quan tâm đến chiều rộng đó, bạn quan tâm đến chiều rộng của vùng văn bản thực tế được lồng bên trong chế độ xem văn bản.

UITextViews, theo mặc định, có đệm xung quanh đường viền của chúng để tạo khoảng trống giữa văn bản đã nhập và cạnh của UITextView rộng vài pixel (và dài cho đầu) ... Để có kích thước chính xác, bạn không nên sử dụng

textView.frame.size.width

nhưng đúng hơn,

textView.frame.size.width-(textView.contentInset.left+textView.contentInset.right+textView.textContainerInset.left+textView.textContainerInset.right+textView.textContainer.lineFragmentPadding/*left*/+textView.textContainer.lineFragmentPadding/*right*/)

^mà có độ rộng của UITextView và trừ ra tất cả các đệm vì vậy bạn còn lại wi th chiều rộng của khu vực văn bản có thể loại.

Đi cùng chiều cao ngoại trừ lineFragmentPadding không có đáy nên bạn chỉ trừ đi một lần thay vì hai lần.


Mã cuối cùng là một cái gì đó như thế này:

CGSize textViewContentSize = CGSizeMake(theTextView.frame.size.width-(theTextView.contentInset.left+theTextView.contentInset.right+theTextView.textContainerInset.left+theTextView.textContainerInset.right+theTextView.textContainer.lineFragmentPadding/*left*/+theTextView.textContainer.lineFragmentPadding/*right*/), theTextView.frame.size.height-(theTextView.contentInset.top+theTextView.contentInset.bottom+theTextView.textContainerInset.top+theTextView.textContainerInset.bottom+theTextView.textContainer.lineFragmentPadding/*top*//*+theTextView.textContainer.lineFragmentPadding*//*there is no bottom padding*/)); 

    CGSize calculatedSize = [theTextView.text sizeWithFont:theTextView.font 
              constrainedToSize:textViewContentSize 
               lineBreakMode:NSLineBreakByWordWrapping]; 


    CGSize adjustedSize = CGSizeMake(ceilf(calculatedSize.width), ceilf(calculatedSize.height)); 
Các vấn đề liên quan