iOS UITableView唤起含UITextView的键盘后内容被导航栏遮挡BUG
解决UITableView滚动内容跑到透明导航栏下方的问题
问题核心原因
- 重复管理输入附件视图:手动将
bottomView添加到控制器视图中,但重写inputAccessoryView时系统会自动处理该视图的布局,重复添加引发布局冲突。 - 未适配安全区域: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
相关产品推荐
相关产品推荐

