Her şeyden önce, metnin nasıl işlendiğine gelince, UITextView ve UILabel arasında büyük bir fark olduğuna dikkat etmek çok önemlidir. UITextView yalnızca tüm kenarlıklarda girintilere sahip olmakla kalmaz, aynı zamanda içindeki metin düzeni de biraz farklıdır.
Bu nedenle, sizeWithFont:UITextViews için gitmenin kötü bir yoludur.
Bunun yerine, UITextViewkendi sizeThatFits:belirleyebileceğiniz UITextViewbir sınırlayıcı kutunun içindeki tüm içeriği görüntülemek için gereken en küçük boyutu döndürecek bir işleve sahiptir .
Aşağıdakiler hem iOS 7 hem de daha eski sürümler için eşit şekilde çalışacaktır ve şu an itibariyle kullanımdan kaldırılan herhangi bir yöntemi içermemektedir.
Basit Çözüm
- (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;
}
Bu işlev, bir NSAttributedStringve istenen genişliği a olarak alacak ve CGFloatgereken yüksekliği döndürecektir.
Ayrıntılı Çözüm
Yakın zamanda benzer bir şey yaptığım için, karşılaştığım bağlantılı Sorunlar için de bazı çözümler paylaşacağımı düşündüm. Umarım birine yardımcı olur.
Bu çok daha derinlemesine ve aşağıdakileri kapsayacak:
- Elbette:
UITableViewCelliçerilen bir içeriğin tüm içeriğini görüntülemek için gereken boyuta göre a'nın yüksekliğini ayarlamakUITextView
- Metin değişikliklerine yanıt verin (ve satırın yükseklik değişikliklerini canlandırın)
- İmleci görünen alanın içinde tutmak ve düzenleme
UITextViewsırasında yeniden boyutlandırırken ilk müdahaleyi UITableViewCellyapmak
Statik bir tablo görünümüyle çalışıyorsanız veya yalnızca bilinen sayıda UITextViewURL'niz varsa, 2. adımı çok daha basit hale getirebilirsiniz.
1. Önce, heightForRowAtIndexPath'in üzerine yazın:
- (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. Gerekli yüksekliği hesaplayan işlevi tanımlayın:
Bir ekleme NSMutableDictionary(denilen bu örnekte textViewsbir örnek değişkeni olarak) sizinUITableViewControllerAlt sınıfınıza .
Bu sözlüğü, aşağıdaki UITextViewsgibi bireye yapılan referansları saklamak için kullanın :
(ve evet, indexPaths sözlükler için geçerli anahtarlardır )
- (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;
}
Bu fonksiyon şimdi gerçek yüksekliği hesaplayacaktır:
- (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. Düzenleme Sırasında Yeniden Boyutlandırmayı Etkinleştir
Sonraki iki işlev için, temsilcisinin UITextViewssizin için ayarlanması önemlidir UITableViewController. Temsilci olarak başka bir şeye ihtiyacınız varsa, oradan ilgili aramaları yaparak veya uygun NSNotificationCenter kancalarını kullanarak bunun üstesinden gelebilirsiniz.
- (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. Düzenleme sırasında imleci takip edin
- (void)textViewDidBeginEditing:(UITextView *)textView {
[self scrollToCursorForTextView:textView];
}
Bu UITableView, UITableView’un görünür Rect’i içinde değilse , kaydırmayı imlecin konumuna getirecektir :
- (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. İç kısımları ayarlayarak görünür yönünü ayarlayın
Düzenleme sırasında, bazı kısımlarınız UITableViewKlavye kapsamında olabilir. Tablo görünümleri girintileri ayarlanmadıysa, scrollToCursorForTextView:tablo görünümünün altındaysa imlecinize kaydırılamayacaktır.
- (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];
}
Ve son kısım:
Görünümünüzün içinde yüklendi, Klavye değişiklikleri için şu yollarla kaydolun 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];
}
Bu cevabı bu kadar uzun süre verdiğim için lütfen bana kızma. Soruyu cevaplamak için hepsine ihtiyaç duyulmasa da, bu doğrudan bağlantılı sorunların yardımcı olacağı başka insanların da olduğuna inanıyorum.
GÜNCELLEME:
Dave Haupert'in belirttiği gibi, rectVisibleişlevi eklemeyi unuttum :
- (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);
}
Ayrıca scrollToCursorForTextView:, projemdeki TextField'lardan birine hala doğrudan bir referans olduğunu fark ettim . bodyTextViewBulunamamakla ilgili bir sorununuz varsa , işlevin güncellenmiş sürümünü kontrol edin.