你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> iOS UITextView 輸入內容實時更新cell的高度

iOS UITextView 輸入內容實時更新cell的高度

編輯:IOS開發基礎

這篇文章介紹了在一個動態數據的 table view 中,cell 根據 text view 內容的輸入實時改變 cell 和 table view 的高度。自動計算 cell 高度的功能使用 iOS 8 才支持的自適應 cell,如果你還不知道 iOS 8 自適應 cell,可以參看這篇文章:iOS 8 自適應 Cell

先上圖,我們最終要實現的效果是這樣的:

63.gif

圖 1:實時更新 cell 高度

實現上面效果的基本原理是:

  1. 在 cell 中設置好 text view 的 autolayout,讓 cell 可以根據內容自適應大小

  2. text view 中輸入內容,根據內容更新 textView 的高度

  3. 調用 tableView 的 beginUpdates 和 endUpdates,重新計算 cell 的高度

  4. 將 text view 更新後的數據保存,以免 table view 滾動超過一屏再滾回來 text view 中的數據又不刷新成原來的數據了。

功能具體實現方法

新建一個項目,拉出 TableViewController,在 cell 上添加一個 UITextView。

首先設置 text view 的 autolayout,比較關鍵的 constraint 是要設置 textView 的高度大於等於一個值。如圖:

302.jpg

圖 2: Text view 的 autolayout 設置

然後,設置 UITextView 的 scrollEnable 為 NO。這一點很關鍵,如果不設置為 NO,UITextView 在內容超出 frame 後,重新設置 text view 的高度會失效,並出現滾動條。

302.jpg

圖 3:去掉 scrolling enable 勾選

根據剛才在 storyboard 中創建的 cell,新建一個 UITableViewCell 類。

#import 
@interface TextViewCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UITextView *textView;
@end

創建 TableViewController 並初始化一些數據

#import "TableViewController.h"
#import "TextViewCell.h"
@interface TableViewController ()
@property (nonatomic, strong) NSArray *data;
@end
@implementation TableViewController
- (void)viewDidLoad {
  [super viewDidLoad];
  //  支持自適應 cell
  self.tableView.estimatedRowHeight = 100;
  self.tableView.rowHeight = UITableViewAutomaticDimension;
  self.data = @[@"Cell 1 ", @"Cell 2", @"Cell 3", @"Cell 4", @"Cell 5", @"Cell 6", @"Cell 7", @"Cell 8"];
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  return [self.data count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  TextViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TextViewCell" forIndexPath:indexPath];
  cell.textView.text = self.data[indexPath.row];
  return cell;
}

使用上面的代碼項目已經可以運行了,但是 text view 還不能自動更新大小,下面來實現 text view 根據內容計算高度。

先在 storyboard 中,將 UITextView 的 delegate 設置為 cell

302.jpg

圖 4:設置 UITextView 的 delegate 為 cell

在 TextViewCell.m 中實現 - (void)textViewDidChange:(UITextView *)textView,每次 text view 內容改變的時候,就重新計算一次 text view 的大小,並讓 table view 更新高度。

#import "TextViewCell.h"
@implementation TextViewCell
- (void)textViewDidChange:(UITextView *)textView
{
  CGRect bounds = textView.bounds;
  // 計算 text view 的高度
  CGSize maxSize = CGSizeMake(bounds.size.width, CGFLOAT_MAX);
  CGSize newSize = [textView sizeThatFits:maxSize];
  bounds.size = newSize;
  textView.bounds = bounds;
  // 讓 table view 重新計算高度
  UITableView *tableView = [self tableView];
  [tableView beginUpdates];
  [tableView endUpdates];
}
- (UITableView *)tableView
{
  UIView *tableView = self.superview;
  while (![tableView isKindOfClass:[UITableView class]] && tableView) {
    tableView = tableView.superview;
  }
  return (UITableView *)tableView;
}
@end

這樣就已經實現了 text view 改變內容自動更新 cell 高度的功能,這篇文章沒有涉及到計算 cell 高度的代碼,因為計算 cell 高度的工作全部交給 iOS 8 的 autolayout 自動計算了,這讓我們少寫了許多令人痛苦的代碼。

最後:為了防止 table view 過長,導致滾動後重新加載 cell,會讓 text view 中的內容還原的問題,我們應該在更新了 text view 的內容之後保存數據。(如果是在編輯狀態下,還需要考慮取消編輯後的回滾功能。 普通數組數據,可以保存一個原始數據的副本,如果用戶取消編輯,就設置 data 為原始數據的副本。如果是 NSManagedObject 對象可以使用 NSUndoManage,不過這些已經超出本篇文章的內容范圍了。)

為了在 text view 更新後能讓 TableViewController 中的 data 更新,需要為 cell 添加一個 delegate,在 text view 更新後調用 delegate,TableViewController 中收到 delegate 信息後更新 data。

修改後的 TextViewCell.h

#import 
@protocol TextViewCellDelegate;
@interface TextViewCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UITextView *textView;
@property (weak, nonatomic) id delegate;
@end
@protocol TextViewCellDelegate 
- (void)textViewCell:(TextViewCell *)cell didChangeText:(NSString *)text;
@end

在 TextView.m的 - (void)textViewDidChange:(UITextView *)textView 中添加 delegate 的調用

- (void)textViewDidChange:(UITextView *)textView
{
  if ([self.delegate respondsToSelector:@selector(textViewCell:didChangeText:)]) {
    [self.delegate textViewCell:self didChangeText:textView.text];
  }
  // 計算 text view 的高度
  ...
  // 讓 table view 重新計算高度
  ...
}

最後在 TableViewController.m 的最後實現 TextViewCellDelegate 的方法,更新 data

#pragma mark - TextViewCellDelegate
- (void)textViewCell:(TextViewCell *)cell didChangeText:(NSString *)text
{
  NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
  NSMutableArray *data = [self.data mutableCopy];
  data[indexPath.row] = text;
  self.data = [data copy];
}

總結

從最後的代碼量來看,這個功能在實現上並不難。只要記住的幾點:

  1. 使用 iOS 8 的特性自動計算 cell 高度,或者在 heightForRow 中自己實現計算高度的代碼。

  2. UITextView 的 scrollEnable 要設置 NO

  3. 更新 table view 的高度使用 beginUpdates 和 endUpdates

  4. Text view 更新內容後要保存數據,以免重新加載 cell 時數據丟失

參考

https://pontifex.azurewebsites.net/self-sizing-uitableviewcell-with-uitextview-in-ios-8/

http://stackoverflow.com/questions/50467/how-do-i-size-a-uitextview-to-its-content/26599389#26599389

http://stackoverflow.com/questions/18368567/uitableviewcell-with-uitextview-height-in-ios-7

http://stackoverflow.com/questions/460014/can-you-animate-a-height-change-on-a-uitableviewcell-when-selected

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved