从Nib加载自定义inputAccessoryView出现宽度为0的错误排查
解决InputAccessoryView点击内部TextView弹出键盘时宽度为0的警告问题
这个问题我之前也碰到过,本质是你的CustomInputAccessoryView的intrinsicContentSize设置和布局约束绑定方式不对,导致系统在键盘弹出重新计算布局时无法正确识别视图的宽度。下面是具体的解决方案:
问题原因分析
- 你重写的
intrinsicContentSize返回了CGSize.zero,这会让系统认为这个视图没有固有尺寸,当键盘弹出触发布局更新时,系统无法正确计算宽度,就会抛出那个警告。 - 你在
setupInputAccessoryView里直接设置containerView.frame = self.bounds,这种方式在布局动态变化(比如键盘弹出)时会失效,因为AutoLayout会覆盖手动设置的frame。
具体修复步骤
1. 修正intrinsicContentSize
inputAccessoryView的宽度会由系统自动匹配当前窗口的宽度,我们只需要指定正确的高度即可。修改intrinsicContentSize的实现:
override var intrinsicContentSize: CGSize { // 这里的height换成你实际需要的高度,比如60 return CGSize(width: UIView.noIntrinsicMetric, height: 60) }
UIView.noIntrinsicMetric告诉系统我们不需要指定固有宽度,由系统自动适配窗口。
2. 用AutoLayout约束替代手动设置frame
在setupInputAccessoryView里,去掉containerView.frame = self.bounds,换成添加AutoLayout约束,让containerView完全填充父视图:
func setupInputAccessoryView() { self.translatesAutoresizingMaskIntoConstraints = false Bundle.main.loadNibNamed("CustomInputAccessoryView", owner: self, options: nil) addSubview(containerView) // 禁用containerView的自动转换约束,然后添加四边约束 containerView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ containerView.topAnchor.constraint(equalTo: self.topAnchor), containerView.leadingAnchor.constraint(equalTo: self.leadingAnchor), containerView.trailingAnchor.constraint(equalTo: self.trailingAnchor), containerView.bottomAnchor.constraint(equalTo: self.bottomAnchor) ]) }
这样不管父视图的frame怎么变化,containerView都会自动填充。
3. 确保XIB内的约束正确
检查你的XIB文件:
- 确保
containerView内部的控件(button1、button2、textView)都有正确的约束,比如textView的宽度和containerView关联,按钮有固定宽度和位置约束,避免出现布局冲突。 - 确认XIB的
File's Owner已经正确设置为CustomInputAccessoryView,所有IBOutlet都关联正确。
修改后的完整代码
class CustomInputAccessoryView: UIView { @IBOutlet var containerView: UIView! @IBOutlet var contentView: UIView! @IBOutlet weak var button1: UIButton! @IBOutlet weak var button2: UIButton! @IBOutlet weak var textView: UITextView! override var intrinsicContentSize: CGSize { return CGSize(width: UIView.noIntrinsicMetric, height: 60) // 替换为你的实际高度 } override init(frame: CGRect) { super.init(frame: frame) setupInputAccessoryView() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setupInputAccessoryView() } func setupInputAccessoryView() { self.translatesAutoresizingMaskIntoConstraints = false Bundle.main.loadNibNamed("CustomInputAccessoryView", owner: self, options: nil) addSubview(containerView) // 使用AutoLayout约束containerView containerView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ containerView.topAnchor.constraint(equalTo: topAnchor), containerView.leadingAnchor.constraint(equalTo: leadingAnchor), containerView.trailingAnchor.constraint(equalTo: trailingAnchor), containerView.bottomAnchor.constraint(equalTo: bottomAnchor) ]) } }
这样修改后,你的inputAccessoryView会始终和窗口宽度一致,点击textView弹出键盘时也不会再出现那个宽度为0的警告了。
内容的提问来源于stack exchange,提问作者alionthego
相关产品推荐
相关产品推荐

