在某些情况下尝试自动resize时,键盘扩展在iOS 10中会丢失高度

您可以在此下载一个示例项目来演示以下问题: https : //github.com/DimaVartanian/keyboard-extension-height-bug

在创建键盘扩展并且没有为其组件指定具体高度而是将它们锚定到视图/ inputView时,理论上系统将根据环境和方向确定它们的高度,在某些情况下,高度反而变为0并且键盘被压碎(除了具有混凝土高度的任何东西,例如自我尺寸的标签或按钮)。

这似乎只发生在iOS 10上。在iOS 9上,子视图正确resize以适应默认的自动键盘高度。

这可以表现出几个场景,这个项目演示了一个基本的场景。 它从基本的键盘扩展模板开始,带有默认的“下一个键盘”按钮和它附带的2个大小限制:

self.nextKeyboardButton.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true self.nextKeyboardButton.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true 

接下来,我们创建一个我们想要填充superview空间的其他视图,而不为自己定义具体大小:

 let anotherView = UIView() anotherView.backgroundColor = UIColor.red anotherView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(anotherView) anotherView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true anotherView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true anotherView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true 

现在,假设我们只想将这个新视图锚定到键盘超级视图的底部。 我们会做类似的事情:

 anotherView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true 

结果如下:

iOS 9 在此处输入图像描述

iOS 10 在此处输入图像描述

这种布局正是我们所期望的。 现在,让我们将新视图锚定到下一个键盘按钮的顶部。 我们摆脱了刚刚添加的约束并替换它

 anotherView.bottomAnchor.constraint(equalTo: self.nextKeyboardButton.topAnchor).isActive = true 

逻辑上,结果高度应该相同(由系统确定)

结果现在是这样的:

iOS 9 在此处输入图像描述

iOS 10 在此处输入图像描述

在iOS 9上,它的行为符合预期,但在iOS 10上,灵活的高度视图大小调整为0,剩下的就是固定高度按钮。

没有关于冲突约束的消息。 我试图找出可能导致这种情况的原因以及为什么它只会发生在iOS 10上。

Apple已经回复了我的DTS票证,并告诉我提交错误报告,所以这实际上是一个iOS 10错误。 我已经提交了一个雷达(#28532959),如果得到回复,我会更新这个答案。 如果其他人提出了一个具体的解决方案,允许我仍然使用自动布局来实现自动高度,仍然可以接受答案。

这是我的解决方法。 设备旋转时有点滞后,但它会完成这项工作,直到Apple修复此错误。 我首先想到它与inputView.allowSelfSizing ,但该变量似乎没有改变任何东西。

首先,声明heightConstraint

 var heightConstraint: NSLayoutConstraint! 

viewDidLoad ,添加自定义视图:

 let nibName: String! = UIDevice.isPhone ? "KeyboardViewiPhone" : "KeyboardViewiPad" customView = Bundle.main.loadNibNamed(nibName, owner: self, options: nil)?.first as! UIView customView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(customView) 

像往常一样为宽度添加约束:

 let widthConstraint = NSLayoutConstraint(item: view, attribute: .width, relatedBy: .equal, toItem: customView, attribute: .width, multiplier: 1.0, constant: 0.0) 

为高度添加常量约束:

 heightConstraint = NSLayoutConstraint(item: customView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: view.frame.height) view.addConstraints([widthConstraint, heightConstraint]) 

现在来修复了:

 override func viewDidLayoutSubviews() { heightConstraint.constant = view.bounds.height } 

由于每次view.bounds更改时都会调用viewDidLayoutSubviews ,因此它将正确处理方向更改。

我也遇到了同样的问题。 这是因为Autolayout约束。 只需删除所有约束。 并设置自动resize。 在此处输入图像描述

我通过设置一个新的高度约束来解决它。

在此处输入图像描述

我也遇到了Xcode 8.2中自定义键盘扩展的同样问题。 这是由auto resizing引起的。 就我而言,我以下面的方式解决了这个问题。

最初,我的自定义键盘有3个视图。 在这里,我修复了第一个和最后一个视图的尾随,前导,顶部和高度。 并将中间视图放在图像中。 在此处输入图像描述

之后选择中间视图并在故事板中打开show the size inspector 。 在size inspector,您将找到一个auto resizing的选项。 在那里选择该视图的约束指标。

在此处输入图像描述

选择在设备中运行项目后,它将正常工作而不会遗漏任何视图。

注意: – 它适用于纵向和横向模式。 主要是您不必为中间视图提供约束。

恕我直言,最佳工作解决方案是使用“比例高度”。 例如,在我的情况下,我最终以2个视图结束。 最高的一个得到0.8的高视图,底部 – 0.2。 这不是完美的解决方案,但您仍然可以从自动布局中受益。

成比例的