Trước hết, điều rất quan trọng cần lưu ý là có sự khác biệt lớn giữa UITextView và UILabel khi nói đến cách văn bản được hiển thị. UITextView không chỉ có nội dung trên tất cả các đường viền mà cả bố cục văn bản bên trong nó cũng hơi khác một chút.
Do đó, đây sizeWithFont:là một cách tồi để sử dụng UITextViews.
Thay vào đó, UITextViewbản thân nó có một hàm được gọi là hàm sizeThatFits:này sẽ trả về kích thước nhỏ nhất cần thiết để hiển thị tất cả nội dung UITextViewbên trong hộp giới hạn mà bạn có thể chỉ định.
Các phương pháp sau sẽ hoạt động như nhau cho cả iOS 7 và các phiên bản cũ hơn và tính đến thời điểm hiện tại không bao gồm bất kỳ phương pháp nào không được dùng nữa.
Giải pháp đơn giản
- (CGFloat)textViewHeightForAttributedText: (NSAttributedString*)text andWidth: (CGFloat)width {
UITextView *calculationView = [[UITextView alloc] init];
[calculationView setAttributedText:text];
CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
return size.height;
}
Hàm này sẽ lấy a NSAttributedStringvà chiều rộng mong muốn là a CGFloatvà trả về chiều cao cần thiết
Giải pháp chi tiết
Vì gần đây tôi đã làm điều gì đó tương tự, tôi nghĩ tôi cũng sẽ chia sẻ một số giải pháp cho các Vấn đề được kết nối mà tôi gặp phải. Tôi hy vọng nó sẽ giúp ai đó.
Điều này chuyên sâu hơn nhiều và sẽ bao gồm những điều sau:
- Tất nhiên: đặt chiều cao của a
UITableViewCelldựa trên kích thước cần thiết để hiển thị đầy đủ nội dung của mộtUITextView
- Phản hồi các thay đổi văn bản (và tạo hiệu ứng cho các thay đổi về độ cao của hàng)
- Giữ con trỏ bên trong vùng hiển thị và giữ người trả lời đầu tiên ở chế độ
UITextViewthay đổi kích thước UITableViewCelltrong khi chỉnh sửa
Nếu bạn đang làm việc với chế độ xem bảng tĩnh hoặc bạn chỉ có một số UITextViews đã biết, bạn có thể thực hiện bước 2 đơn giản hơn nhiều.
1. Đầu tiên, hãy ghi đè heightForRowAtIndexPath:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// check here, if it is one of the cells, that needs to be resized
// to the size of the contained UITextView
if ( )
return [self textViewHeightForRowAtIndexPath:indexPath];
else
// return your normal height here:
return 100.0;
}
2. Xác định hàm tính toán chiều cao cần thiết:
Thêm một NSMutableDictionary(trong ví dụ này được gọi là textViews) dưới dạng một biến thể hiện vào UITableViewControllerlớp con của bạn .
Sử dụng từ điển này để lưu trữ các tham chiếu đến cá nhân UITextViewsnhư vậy:
(và vâng, indexPath là khóa hợp lệ cho từ điển )
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Do you cell configuring ...
[textViews setObject:cell.textView forKey:indexPath];
[cell.textView setDelegate: self]; // Needed for step 3
return cell;
}
Hàm này bây giờ sẽ tính toán chiều cao thực tế:
- (CGFloat)textViewHeightForRowAtIndexPath: (NSIndexPath*)indexPath {
UITextView *calculationView = [textViews objectForKey: indexPath];
CGFloat textViewWidth = calculationView.frame.size.width;
if (!calculationView.attributedText) {
// This will be needed on load, when the text view is not inited yet
calculationView = [[UITextView alloc] init];
calculationView.attributedText = // get the text from your datasource add attributes and insert here
textViewWidth = 290.0; // Insert the width of your UITextViews or include calculations to set it accordingly
}
CGSize size = [calculationView sizeThatFits:CGSizeMake(textViewWidth, FLT_MAX)];
return size.height;
}
3. Bật Thay đổi kích thước trong khi Chỉnh sửa
Đối với hai hàm tiếp theo, điều quan trọng là đại biểu của hàm UITextViewsđược đặt thành của bạn UITableViewController. Nếu bạn cần một cái gì đó khác với tư cách là người được ủy quyền, bạn có thể giải quyết vấn đề đó bằng cách thực hiện các lệnh gọi liên quan từ đó hoặc sử dụng các móc NSNotificationCenter thích hợp.
- (void)textViewDidChange:(UITextView *)textView {
[self.tableView beginUpdates]; // This will cause an animated update of
[self.tableView endUpdates]; // the height of your UITableViewCell
// If the UITextView is not automatically resized (e.g. through autolayout
// constraints), resize it here
[self scrollToCursorForTextView:textView]; // OPTIONAL: Follow cursor
}
4. Theo dõi con trỏ trong khi Chỉnh sửa
- (void)textViewDidBeginEditing:(UITextView *)textView {
[self scrollToCursorForTextView:textView];
}
Điều này sẽ làm cho UITableViewcuộn đến vị trí của con trỏ, nếu nó không nằm trong Rect có thể nhìn thấy của UITableView:
- (void)scrollToCursorForTextView: (UITextView*)textView {
CGRect cursorRect = [textView caretRectForPosition:textView.selectedTextRange.start];
cursorRect = [self.tableView convertRect:cursorRect fromView:textView];
if (![self rectVisible:cursorRect]) {
cursorRect.size.height += 8; // To add some space underneath the cursor
[self.tableView scrollRectToVisible:cursorRect animated:YES];
}
}
5. Điều chỉnh trực tràng có thể nhìn thấy, bằng cách cài đặt các bộ phận
Trong khi chỉnh sửa, các phần của bạn UITableViewcó thể bị Bàn phím che mất. Nếu nội dung của chế độ xem bảng không được điều chỉnh, scrollToCursorForTextView:sẽ không thể cuộn đến con trỏ của bạn, nếu con trỏ ở cuối chế độ xem bảng.
- (void)keyboardWillShow:(NSNotification*)aNotification {
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, kbSize.height, 0.0);
self.tableView.contentInset = contentInsets;
self.tableView.scrollIndicatorInsets = contentInsets;
}
- (void)keyboardWillHide:(NSNotification*)aNotification {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.35];
UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, 0.0, 0.0);
self.tableView.contentInset = contentInsets;
self.tableView.scrollIndicatorInsets = contentInsets;
[UIView commitAnimations];
}
Và phần cuối cùng:
Bên trong chế độ xem của bạn đã tải, hãy đăng ký Thông báo cho các thay đổi trên Bàn phím thông qua NSNotificationCenter:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
Xin đừng giận tôi, vì đã làm câu trả lời này quá lâu. Mặc dù không phải tất cả đều cần thiết để trả lời câu hỏi, nhưng tôi tin rằng có những người khác, những người mà những vấn đề liên quan trực tiếp này sẽ hữu ích.
CẬP NHẬT:
Như Dave Haupert đã chỉ ra, tôi đã quên bao gồm rectVisiblehàm:
- (BOOL)rectVisible: (CGRect)rect {
CGRect visibleRect;
visibleRect.origin = self.tableView.contentOffset;
visibleRect.origin.y += self.tableView.contentInset.top;
visibleRect.size = self.tableView.bounds.size;
visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;
return CGRectContainsRect(visibleRect, rect);
}
Ngoài ra, tôi nhận thấy, điều đó scrollToCursorForTextView:vẫn bao gồm một tham chiếu trực tiếp đến một trong các Trường Văn bản trong dự án của tôi. Nếu bạn gặp sự cố bodyTextViewkhông tìm thấy, hãy kiểm tra phiên bản cập nhật của chức năng.