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, UITextView
kendi sizeThatFits:
belirleyebileceğiniz UITextView
bir 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 NSAttributedString
ve istenen genişliği a olarak alacak ve CGFloat
gereken 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:
UITableViewCell
iç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
UITextView
sırasında yeniden boyutlandırırken ilk müdahaleyi UITableViewCell
yapmak
Statik bir tablo görünümüyle çalışıyorsanız veya yalnızca bilinen sayıda UITextView
URL'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 textViews
bir örnek değişkeni olarak) sizinUITableViewController
Alt sınıfınıza .
Bu sözlüğü, aşağıdaki UITextViews
gibi 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 UITextViews
sizin 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 UITableView
Klavye 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, rectVisible
iş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 . bodyTextView
Bulunamamakla ilgili bir sorununuz varsa , işlevin güncellenmiş sürümünü kontrol edin.