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

iOS UITableView唤起含UITextView的键盘后内容被导航栏遮挡BUG

解决UITableView滚动内容跑到透明导航栏下方的问题

问题核心原因

  1. 重复管理输入附件视图:手动将bottomView添加到控制器视图中,但重写inputAccessoryView时系统会自动处理该视图的布局,重复添加引发布局冲突。
  2. 未适配安全区域:UITableView的顶部约束直接对齐到父视图,没有考虑透明导航栏占据的安全区域空间,导致滚动时内容偏移到导航栏下方。

修复后的完整代码

import UIKit
import SnapKit

let numberOfRows = 15

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet var myTableView: UITableView!
    
    let textView = UITextView()
    let bottomView = UIView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        myTableView.keyboardDismissMode = .interactive
        // 确保tableView自动适配安全区域与键盘变化
        myTableView.contentInsetAdjustmentBehavior = .automatic
        
        bottomView.backgroundColor = .darkGray
        bottomView.addSubview(textView)
        
        textView.backgroundColor = .black
        textView.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(10)
        }
        textView.text = "Type something.."
        
        // 代码创建tableView时,强制对齐安全区域顶部(Storyboard创建可直接在界面设置)
        if myTableView.superview != nil {
            myTableView.snp.makeConstraints { make in
                make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
                make.left.right.bottom.equalToSuperview()
            }
        }
    }
    
    override var inputAccessoryView: UIView {
        return bottomView
    }
    
    // 必须重写该属性,让系统识别自定义输入附件视图
    override var canBecomeFirstResponder: Bool {
        return true
    }
        
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }
    
    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return 200
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return numberOfRows
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
        
        cell.textLabel?.text = "Row \(indexPath.row)"
        cell.detailTextLabel?.text = "Tastes very close to Snickers chocolate bar. Only tried because of reviews. Would purchase again if price wasn’t so high, and available in Canada."
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        navigationController?.pushViewController(UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DetailVC"), animated: true)
    }
}

关键修改说明

  • 移除手动添加bottomView的代码:inputAccessoryView的视图由系统自动管理布局,无需手动添加到控制器视图中。
  • 添加canBecomeFirstResponder重写:这是自定义输入附件视图生效的必要条件,否则系统不会加载你定义的bottomView。
  • 适配安全区域约束:将UITableView顶部对齐到safeAreaLayoutGuide,确保内容从导航栏下方开始渲染,滚动时不会进入导航栏区域。
  • 设置contentInsetAdjustmentBehavior:让iOS 11+系统自动处理滚动视图的内边距适配,兼容键盘弹出/收起、安全区域变化等场景。

额外提示

如果UITableView是通过Storyboard创建的,可直接在界面编辑器中把tableView的Top约束连接到Safe Area Top,替代代码中的约束设置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 06:12:44