You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS开发:如何实现UITableViewCell随TextView输入内容自动展开?

Fixing Auto-Expanding UITableViewCell with Embedded TextView

Hey there, let's work through this issue where you want a UITableViewCell to automatically expand as the user types into an embedded TextView. You mentioned you've tried setting automatic row height, so let's fill in the gaps and make this work reliably.

Step 1: Configure the UITableView Basics

First, confirm you've set up the table view to use automatic dimension correctly. This is the foundation, but it needs to be paired with proper cell layout:

override func viewDidLoad() {
    super.viewDidLoad()
    // Enable automatic row height calculation
    tableView.rowHeight = UITableView.automaticDimension
    // Set a reasonable estimated height (adjust based on your cell's default size)
    tableView.estimatedRowHeight = 60
}

Step 2: Set Up the UITableViewCell & TextView Constraints

Your cell's TextView needs specific setup to let it drive the cell's height:

  • In your custom cell (either via storyboard/XIB or code):
    1. Add a TextView to the cell's contentView.
    2. Pin the TextView to the contentView with top, bottom, leading, and trailing constraints (leave 8-10 point margins for padding).
    3. Disable scrolling on the TextView—this is critical! If scrolling is enabled, the TextView won't expand vertically to fit its content:
      textView.isScrollEnabled = false
      
    4. Optional: Adjust the TextView's text container insets to prevent text from touching the edges:
      textView.textContainerInset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
      

Step 3: Handle TextView Content Changes

When the user types, you need to tell the table view to recalculate the cell's height. Here's how to do it smoothly:

Assign the TextView Delegate

In your cellForRowAt method, set the TextView's delegate to your view controller (or handle it directly in the cell if you prefer):

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellID", for: indexPath) as! YourCustomCell
    cell.textView.text = yourDataSource[indexPath.row]
    cell.textView.delegate = self
    return cell
}

Implement textViewDidChange

Use beginUpdates() and endUpdates() to trigger a smooth height recalculation—this avoids the jarring effect of reloading the row:

func textViewDidChange(_ textView: UITextView) {
    // Find the corresponding cell and index path
    guard let cell = textView.superview?.superview as? YourCustomCell,
          let indexPath = tableView.indexPath(for: cell) else {
        return
    }
    
    // Update your data source with the new text
    yourDataSource[indexPath.row] = textView.text
    
    // Tell the table view to recalculate the row height
    tableView.beginUpdates()
    tableView.endUpdates()
    
    // Optional: Scroll to keep the TextView visible as it expands
    tableView.scrollToRow(at: indexPath, at: .none, animated: true)
}

Optional: Alternative Approach (Manual Height Calculation)

If automatic dimension isn't working for edge cases, you can calculate the TextView's height manually:

Add a String Extension to Calculate Text Height

extension String {
    func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(
            with: constraintRect,
            options: .usesLineFragmentOrigin,
            attributes: [.font: font],
            context: nil
        )
        return ceil(boundingBox.height)
    }
}

Implement heightForRowAt

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    let text = yourDataSource[indexPath.row]
    // Calculate available width (subtract cell margins)
    let availableWidth = tableView.bounds.width - 16 // Adjust based on your constraints
    // Calculate text height, add margins for the cell
    let textHeight = text.height(withConstrainedWidth: availableWidth, font: UIFont.systemFont(ofSize: 16))
    return textHeight + 16 // Add top/bottom margins
}

Update in textViewDidChange

func textViewDidChange(_ textView: UITextView) {
    guard let cell = textView.superview?.superview as? YourCustomCell,
          let indexPath = tableView.indexPath(for: cell) else {
        return
    }
    yourDataSource[indexPath.row] = textView.text
    tableView.reloadRows(at: [indexPath], with: .automatic)
}

Common pitfalls to avoid:

  • Forgetting to disable isScrollEnabled on the TextView—this is the #1 reason automatic expansion fails.
  • Missing constraints between the TextView and cell's contentView—the table view needs clear layout cues to calculate height.
  • Using an unrealistic estimatedRowHeight—pick a value close to your cell's default height to prevent layout jumping.

内容的提问来源于stack exchange,提问作者Parv Bhasker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:57:51