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.
attributedText
tanpa menentukan font, warna dan teks keselarasan mengarah ke pengaturan nilai default dari atribut NSAttributedString ke textView. Dalam kasus saya itu menyebabkan mendapatkan ketinggian yang berbeda dari tampilan teks untuk teks yang sama.Ada fungsi baru untuk menggantikan sizeWithFont, yaitu boundingRectWithSize.
Saya menambahkan fungsi berikut ke proyek saya, yang memanfaatkan fungsi baru di iOS7 dan yang lama di iOS lebih rendah dari 7. Ini pada dasarnya memiliki sintaks yang sama dengan sizeWithFont:
Anda dapat menambahkan IOS_NEWER_OR_EQUAL_TO_7 itu pada file prefix.pch Anda di proyek Anda sebagai:
sumber
Jika Anda menggunakan UITableViewAutomaticDimension, saya memiliki solusi yang sangat sederhana (khusus iOS 8). Dalam kasus saya ini adalah tampilan tabel statis, tetapi saya rasa Anda dapat menyesuaikan ini untuk prototipe dinamis ...
Saya memiliki outlet kendala untuk ketinggian tampilan teks dan saya telah menerapkan metode berikut seperti ini:
Tapi ingat : tampilan teks harus dapat di-scroll, dan Anda harus menyiapkan pembatas Anda agar berfungsi untuk dimensi otomatis:
Contoh sel paling dasar adalah:
sumber
Jawaban Tim Bodeit bagus. Saya menggunakan kode Simple Solution untuk mendapatkan tinggi tampilan teks dengan benar, dan menggunakan ketinggian itu di
heightForRowAtIndexPath
. Tapi saya tidak menggunakan jawaban lainnya untuk mengubah ukuran tampilan teks. Sebagai gantinya, saya menulis kode untuk mengubahframe
tampilan tekscellForRowAtIndexPath
.Semuanya berfungsi di iOS 6 ke bawah, tetapi di iOS 7 teks dalam tampilan teks tidak dapat ditampilkan sepenuhnya meskipun
frame
tampilan teks memang diubah ukurannya. (Saya tidak menggunakanAuto Layout
). Itu harus menjadi alasan bahwa di iOS 7 adaTextKit
dan posisi teks dikontrol olehNSTextContainer
inUITextView
. Jadi dalam kasus saya, saya perlu menambahkan baris untuk mengatursomeTextView
agar berfungsi dengan benar di iOS 7.Seperti yang dikatakan dalam dokumentasi, apa yang dilakukan properti itu adalah:
Jika dibiarkan dengan nilai default, setelah mengubah ukuran
frame
darisomeTextView
, ukurantextContainer
tidak akan berubah, sehingga teks hanya dapat ditampilkan di area sebelum diubah ukurannya.Dan mungkin diperlukan untuk mengatur
scrollEnabled = NO
seandainya ada lebih dari satutextContainer
, sehingga teks akan mengalir dari satutextContainer
ke yang lain.sumber
Berikut satu solusi lagi yang bertujuan untuk kesederhanaan dan pembuatan prototipe cepat :
Mempersiapkan:
UITextView
dengan konten lainnya.TableCell.h
.UITableView
dikaitkan denganTableViewController.h
.Larutan:
(1) Tambahkan ke
TableViewController.m
:(2) Tambahkan ke
TableCell.m
:Penjelasan:
Jadi yang terjadi di sini adalah: setiap tampilan teks terikat ke tinggi sel tabel dengan batasan vertikal dan horizontal - itu berarti ketika tinggi sel tabel meningkat, tampilan teks juga akan meningkatkan ukurannya. Saya menggunakan versi modifikasi dari kode @ manecosta untuk menghitung tinggi tampilan teks yang diperlukan agar sesuai dengan teks yang diberikan dalam sel. Jadi itu artinya diberi teks dengan jumlah karakter X,
frameForText:
akan mengembalikan ukuran yang akan memiliki propertisize.height
yang sesuai dengan tinggi tampilan teks yang dibutuhkan.Sekarang, yang tersisa hanyalah memperbarui tinggi sel agar sesuai dengan tinggi tampilan teks yang diperlukan. Dan ini dicapai pada
heightForRowAtIndexPath:
. Seperti disebutkan di komentar, karenasize.height
hanya tinggi untuk tampilan teks dan bukan seluruh sel, harus ada beberapa offset yang ditambahkan ke dalamnya. Dalam kasus contoh, nilainya adalah 80.sumber
dream.dream
adalah teks yang saya render dalam tampilan teks.Satu pendekatan jika Anda menggunakan tata letak otomatis adalah membiarkan mesin tata letak otomatis menghitung ukuran untuk Anda. Ini bukan pendekatan yang paling efisien tetapi cukup nyaman (dan bisa dibilang paling akurat). Ini menjadi lebih nyaman karena kompleksitas tata letak sel tumbuh - misalnya, tiba-tiba Anda memiliki dua atau lebih tampilan teks / bidang dalam sel.
Saya menjawab pertanyaan serupa dengan sampel lengkap untuk mengukur sel tableview menggunakan tata letak otomatis, di sini:
Bagaimana cara mengubah ukuran superview agar sesuai dengan semua subview dengan autolayout?
sumber
Solusi mulus lengkap adalah sebagai berikut.
Pertama, kita membutuhkan kelas sel dengan textView
Selanjutnya, kami menggunakannya di TableViewController
Di sini
minLines
memungkinkan untuk menyetel tinggi minimum untuk textView (untuk menahan meminimalkan ketinggian dengan AutoLayout dengan UITableViewAutomaticDimension).moveRowAtIndexPath:indexPath:
dengan indexPath yang sama memulai penghitungan ulang tinggi tableViewCell dan tata letak ulang.performWithoutAnimation:
menghapus efek samping (offset konten tableView melompat saat memulai baris baru saat mengetik).Penting untuk mempertahankan
relativeFrameOriginY
(bukancontentOffsetY
!) Selama pembaruan sel karenacontentSize
sel sebelum sel saat ini dapat diubah oleh kalkulus autoLayout dengan cara yang tidak terduga. Ini menghilangkan lompatan visual pada tanda hubung sistem saat mengetik kata-kata panjang.Perhatikan bahwa Anda tidak boleh menyetel properti
estimatedRowHeight
! Berikut ini tidak berhasilGunakan hanya metode tableViewDelegate.
================================================== ========================
Jika seseorang tidak keberatan dengan pengikatan lemah antara tableView dan tableViewCell serta memperbarui geometri tableView dari tableViewCell ,
TextInputTableViewCell
kelas di atas dapat ditingkatkan :sumber
Tinggi sel Anda akan dihitung oleh konten UILabel, tetapi semua teks akan ditampilkan oleh BidangTeks.
sumber
Saya rasa dengan cara ini Anda dapat menghitung tinggi tampilan teks Anda dan kemudian mengubah ukuran sel tampilan tabel Anda sesuai dengan ketinggian itu sehingga Anda dapat menampilkan teks lengkap pada sel
sumber
Versi cepat
sumber
Jika Anda ingin menyesuaikan
UITableViewCell
ketinggian secara otomatis berdasarkan ketinggian bagian dalamUITextView
. Lihat jawaban saya di sini: https://stackoverflow.com/a/45890087/1245231Solusinya cukup sederhana dan harus bekerja sejak iOS 7. Pastikan bahwa
Scrolling Enabled
opsi diaktifkan off untukUITextView
dalamUITableViewCell
dalam storyboard.Kemudian di viewDidLoad () UITableViewController Anda, setel
tableView.rowHeight = UITableViewAutomaticDimension
dantableView.estimatedRowHeight > 0
seperti:Itu dia.
UITableViewCell
Ketinggian akan secara otomatis disesuaikan berdasarkan tinggi bagian dalamUITextView
.sumber
Untuk iOS 8 ke atas, Anda cukup menggunakan
your_tablview.estimatedrowheight= minheight
kamu inginsumber