Pertama-tama, sangat penting untuk diperhatikan, bahwa ada perbedaan besar antara UITextView dan UILabel dalam hal bagaimana teks ditampilkan. UITextView tidak hanya memiliki sisipan di semua perbatasan, tetapi juga tata letak teks di dalamnya sedikit berbeda.
Oleh karena itu, sizeWithFont:adalah cara yang buruk untuk menggunakan UITextView.
Sebaliknya UITextViewsendiri memiliki fungsi yang disebut sizeThatFits:yang akan mengembalikan ukuran terkecil yang diperlukan untuk menampilkan semua konten di UITextViewdalam kotak pembatas, yang dapat Anda tentukan.
Berikut ini akan bekerja sama untuk iOS 7 dan versi yang lebih lama dan untuk saat ini tidak termasuk metode apa pun, yang tidak digunakan lagi.
Solusi Sederhana
- (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;
}
Fungsi ini akan mengambil a NSAttributedStringdan lebar yang diinginkan sebagai a CGFloatdan mengembalikan tinggi yang dibutuhkan
Solusi Terperinci
Karena saya baru-baru ini melakukan sesuatu yang serupa, saya pikir saya juga akan membagikan beberapa solusi untuk Masalah terkait yang saya temui. Saya berharap ini akan membantu seseorang.
Ini jauh lebih mendalam dan akan mencakup hal-hal berikut:
- Tentunya: pengaturan tinggi sebuah
UITableViewCellberdasarkan ukuran yang dibutuhkan untuk menampilkan konten yang lengkapUITextView
- Merespons perubahan teks (dan menganimasikan perubahan ketinggian baris)
- Menjaga kursor di dalam area yang terlihat dan menjaga responden pertama di
UITextViewsaat mengubah ukuran UITableViewCellsaat mengedit
Jika Anda bekerja dengan tampilan tabel statis atau Anda hanya memiliki jumlah UITextViews yang diketahui , Anda dapat membuat langkah 2 jauh lebih sederhana.
1. Pertama, timpa 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. Tentukan fungsi yang menghitung ketinggian yang dibutuhkan:
Tambahkan NSMutableDictionary(dalam contoh ini disebut textViews) sebagai variabel instan ke AndaUITableViewController subkelas .
Gunakan kamus ini untuk menyimpan referensi ke individu UITextViewsseperti:
(dan ya, indexPaths adalah kunci yang valid untuk kamus )
- (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;
}
Fungsi ini sekarang akan menghitung tinggi sebenarnya:
- (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. Aktifkan Pengubahan Ukuran sambil Mengedit
Untuk dua fungsi berikutnya, penting, bahwa delegasi UITextViewsdiatur ke Anda UITableViewController. Jika Anda membutuhkan sesuatu yang lain sebagai delegasi, Anda dapat mengatasinya dengan membuat panggilan yang relevan dari sana atau menggunakan hook NSNotificationCenter yang sesuai.
- (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. Ikuti kursor saat Mengedit
- (void)textViewDidBeginEditing:(UITextView *)textView {
[self scrollToCursorForTextView:textView];
}
Ini akan membuat UITableViewscroll ke posisi kursor, jika tidak berada di dalam Rect yang terlihat dari 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. Sesuaikan persegi yang terlihat, dengan mengatur insets
Saat mengedit, sebagian dari Anda UITableViewmungkin dilindungi oleh Keyboard. Jika sisipan tampilan tabel tidak disesuaikan, scrollToCursorForTextView:tidak akan dapat menggulir ke kursor Anda, jika berada di bagian bawah tampilan tabel.
- (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];
}
Dan bagian terakhir:
Di dalam tampilan Anda dimuat, daftar untuk Pemberitahuan untuk perubahan Keyboard melalui 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];
}
Tolong jangan marah padaku, karena membuat jawaban ini begitu lama. Meskipun tidak semuanya diperlukan untuk menjawab pertanyaan, saya yakin bahwa ada orang lain yang dapat membantu masalah yang terkait langsung ini.
MEMPERBARUI:
Seperti yang ditunjukkan Dave Haupert, saya lupa menyertakan rectVisiblefungsinya:
- (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);
}
Juga saya perhatikan, itu scrollToCursorForTextView:masih menyertakan referensi langsung ke salah satu BidangTeks di proyek saya. Jika Anda memiliki masalah dengan bodyTextViewtidak ditemukannya, periksa versi terbaru dari fungsi tersebut.