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

inputAccessoryView未激活时无高度致内容遮挡问题求助

解决方案

问题根源在于你固定了collectionView的底部内边距,而inputAccessoryView的高度在未激活和激活状态下(键盘弹出/收起)会变化,导致内边距要么不足要么冗余。核心思路是动态根据inputAccessoryView的高度以及键盘状态调整collectionView的内边距。

步骤1:修改初始化配置

在viewDidLoad中,移除固定的底部内边距设置,改为只保留顶部内边距,并关闭系统自动内边距调整,方便手动控制:

override func viewDidLoad() {
    super.viewDidLoad()
    
    collectionView?.register(ChatMessageCell.self, forCellWithReuseIdentifier: cellId)
    // 只保留顶部内边距,底部内边距后续动态设置
    collectionView?.contentInset = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0)
    collectionView?.backgroundColor = .moonNavy
    collectionView?.alwaysBounceVertical = true
    collectionView?.keyboardDismissMode = .interactive
    // 关闭系统自动内边距调整,改为手动控制
    collectionView?.contentInsetAdjustmentBehavior = .never
    
    loadCurrentUserObject()
    setupKeyboardObserve()
}

步骤2:添加高度跟踪与内边距更新

添加变量跟踪inputAccessoryView的当前高度,并在布局变化时更新内边距:

// 跟踪inputAccessoryView的当前高度
private var accessoryViewCurrentHeight: CGFloat = 0

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    guard let accessoryView = inputAccessoryView else { return }
    let newHeight = accessoryView.frame.height
    
    // 高度变化时才更新内边距,避免重复操作
    if newHeight != accessoryViewCurrentHeight {
        accessoryViewCurrentHeight = newHeight
        updateCollectionViewBottomInset(withKeyboardHeight: 0)
    }
}

// 统一更新collectionView底部内边距的方法
private func updateCollectionViewBottomInset(withKeyboardHeight keyboardHeight: CGFloat) {
    guard var inset = collectionView?.contentInset else { return }
    // 底部内边距 = 键盘高度 + inputAccessoryView高度 + 原有间距8
    inset.bottom = keyboardHeight + accessoryViewCurrentHeight + 8
    collectionView?.contentInset = inset
    collectionView?.scrollIndicatorInsets = inset
}

步骤3:处理键盘弹出/收起事件

修改键盘通知监听方法,在键盘状态变化时更新内边距:

func setupKeyboardObserve() {
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}

@objc private func keyboardWillShow(_ notification: Notification) {
    guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
    let keyboardHeight = keyboardFrame.height
    updateCollectionViewBottomInset(withKeyboardHeight: keyboardHeight)
}

@objc private func keyboardWillHide(_ notification: Notification) {
    updateCollectionViewBottomInset(withKeyboardHeight: 0)
}

步骤4:确保inputAccessoryView初始化时高度正确

在inputAccessoryView的getter方法末尾添加布局强制刷新,确保初始化时就能获取到正确高度:

override var inputAccessoryView: UIView? {
    if (_inputAccessoryView == nil ){
        // ... 你的原有初始化代码
        
        textViewDidChange(textView)
        // 强制刷新布局,计算正确高度
        _inputAccessoryView.layoutIfNeeded()
    }
    return _inputAccessoryView
}

关键说明

  1. 关闭contentInsetAdjustmentBehavior = .never是为了避免系统自动调整内边距与手动设置冲突;
  2. viewDidLayoutSubviews会在每次布局变化时触发,确保inputAccessoryView高度变化后能及时更新内边距;
  3. 统一用updateCollectionViewBottomInset方法处理内边距,避免代码重复;
  4. 初始化时强制刷新inputAccessoryView布局,保证初始高度计算正确,解决未激活时的遮挡问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:55:23