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 UITextView
sendiri memiliki fungsi yang disebut sizeThatFits:
yang akan mengembalikan ukuran terkecil yang diperlukan untuk menampilkan semua konten di UITextView
dalam 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 NSAttributedString
dan lebar yang diinginkan sebagai a CGFloat
dan 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
UITableViewCell
berdasarkan 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
UITextView
saat mengubah ukuran UITableViewCell
saat mengedit
Jika Anda bekerja dengan tampilan tabel statis atau Anda hanya memiliki jumlah UITextView
s 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 UITextViews
seperti:
(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 UITextViews
diatur 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 UITableView
scroll 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 UITableView
mungkin 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 rectVisible
fungsinya:
- (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 bodyTextView
tidak ditemukannya, periksa versi terbaru dari fungsi tersebut.