我有一个具有以下结构的ViewController((x)
表示级别):
UIViewController (1)
- NavigationBar (2)
- UIScrollView (2)
- UIView (3)
- UITextField (4)
- UITextField (4)
- UITextField (4)
- UITextField (4)
- UIButton (4)
4
的所有元素彼此垂直约束,间距为16。4
的第一个和最后一个元素被限制在UIView的(3
)顶部和底部。3
)的顶部和底部被限制在UIScrollView(2
)。2
)被限制在NavigationBar的底部(2
)和超级视图的底部(1
)UIView(3
)具有以下约束:
在viewController的viewDidLoad
中,我称之为:
registerForKeyboardWillShowNotification(self.scrollView)
registerForKeyboardWillHideNotification(self.scrollView)
registerForKeyboard...ShowNotification
是UIViewController
的扩展名:
extension UIViewController
{
/// Act when keyboard is shown, by adding contentInsets to the scrollView.
func registerForKeyboardWillShowNotification(_ scrollView: UIScrollView, usingBlock block: ((CGSize?) -> Void)? = nil)
{
_ = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification,
object: nil, queue: nil)
{ notification in
let userInfo = notification.userInfo!
let keyboardSize = (userInfo[UIResponder.keyboardFrameEndUserInfoKey]! as AnyObject).cgRectValue.size
let contentInsets = UIEdgeInsets(top: scrollView.contentInset.top,
left: scrollView.contentInset.left,
bottom: keyboardSize.height,
right: scrollView.contentInset.right)
scrollView.contentInset = contentInsets
block?(keyboardSize)
}
}
/// Act when keyboard is hidden, by removing contentInsets from the scrollView.
func registerForKeyboardWillHideNotification(_ scrollView: UIScrollView, usingBlock block: ((CGSize?) -> Void)? = nil)
{
_ = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification,
object: nil, queue: nil)
{ notification in
let userInfo = notification.userInfo!
let keyboardSize = (userInfo[UIResponder.keyboardFrameEndUserInfoKey]! as AnyObject).cgRectValue.size
let contentInsets = UIEdgeInsets(top: scrollView.contentInset.top,
left: scrollView.contentInset.left,
bottom: 0,
right: scrollView.contentInset.right)
scrollView.contentInset = contentInsets
block?(keyboardSize)
}
}
}
但是,当键盘显示时,它没有插入scrollView(足够大)。我调试了,情况就是这样:
height = 216
height = 260
height = 291
尽管建议栏可能是我的问题,但不是。
在registerForKeyboardWillShowNotification
中,我将bottom: keyboardSize.height
更改为bottom: keyboardSize.height + 30
,得到的结果完全相同(我看到按钮的相同部分部分隐藏在键盘后面)。一旦添加50或更多,它似乎最终会产生很小的变化。
keyboardWillShowNotification
,而不是keyboardDidShowNotification
,这没有什么区别。keyboardFrameEndUserInfoKey
,而不是keyboardFrameBeginUserInfoKey
,这没有什么区别。我在这里想念什么?
不幸的是,我无法解决这个问题,我不确定为什么它不能按预期工作。
但是,我通过使用UIScrollView内的UIStackView得到了预期的行为。我以this article作为参考。
UI布局
[UIScrollView
leading
和trailing
被16限制到超级视图。 top
被导航栏底部的0约束。bottom
被超级视图底部的0约束。[UIStackView
leading
和trailing
被0约束到scrollView。top
和bottom
被24限制到scrollView,以获取所需的NavigationBar间距,以及按钮和键盘之间的间距。axis=vertical
,alignment=fill
,distribution=fill
,spacing=24
。The NavigationBar
NavigationBar是一个自定义类,它从其内容派生其高度。它没有设置高度限制,但是占位符高度为100。NavigationBar将填满整个屏幕。这可以通过以下方法解决:删除占位符的高度,并以低优先级(在这种情况下,优先级为1
)添加any高度约束。
现在可以使用应用键盘插入的初始代码。
/// Act when keyboard is shown, by adding contentInsets to the scrollView.
func registerForKeyboardWillShowNotification(_ scrollView: UIScrollView, usingBlock block: ((CGSize?) -> Void)? = nil)
{
_ = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification,
object: nil, queue: nil)
{ notification in
let userInfo = notification.userInfo!
let keyboardSize = (userInfo[UIResponder.keyboardFrameEndUserInfoKey]! as AnyObject).cgRectValue.size
let contentInsets = UIEdgeInsets(top: scrollView.contentInset.top,
left: scrollView.contentInset.left,
bottom: keyboardSize.height,
right: scrollView.contentInset.right)
scrollView.contentInset = contentInsets
block?(keyboardSize)
}
}