【发布时间】:2020-09-08 17:09:08
【问题描述】:
对我有用的解决方案
经过几天的努力,我终于找到了解决视图动画问题的方法。对我来说 keyboardWillChangeFrameNotification 有效。解决方案在以下线程中讨论:
Move textfield when keyboard appears swift
我在堆栈视图中嵌入了一堆视图以及文本视图。我给了
@objc func keyboardWillShow(notification:NSNotification) {
guard let keyboardValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
let keyboardScreenEndFrame = keyboardValue.cgRectValue
let keyboardFrame = view.convert(keyboardScreenEndFrame, from: view.window)
if #available(iOS 11.0, *) {
scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardFrame.height - view.safeAreaInsets.bottom, right: 0)
} else {
scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardFrame.height, right: 0)
}
scrollView.scrollIndicatorInsets = scrollView.contentInset
let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height + keyboardFrame.height - scrollView.bounds.size.height)
scrollView.setContentOffset(bottomOffset, animated: true)
UIView.animate(withDuration: 0.5, animations: { () -> Void in
self.view.layoutIfNeeded()
})
}
===
extension FirstViewController: UITextViewDelegate {
func textViewDidChange(_ textView: UITextView) {
let estimatedSize = textView.sizeThatFits(textView.frame.size)
if estimatedSize.height > textViewMaxHeight {
if estimatedSize.height - textViewMaxHeight < textView.font!.lineHeight && !didExpandTextView {
didExpandTextView = true
var contentInset:UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: self.savedKbHeight, right: 0.0)
if let v = self.tabBarController?.tabBar {
contentInset.bottom -= v.frame.height
}
scrollView.contentInset = contentInset
scrollView.scrollIndicatorInsets = contentInset
if textView.isFirstResponder {
let fr = textView.frame
scrollView.scrollRectToVisible(fr, animated: false)
}
}
textView.isScrollEnabled = true
textView.showsVerticalScrollIndicator = true
} else {
if let lineHeight = textView.font?.lineHeight, Int(estimatedSize.height / lineHeight) != numberOfLines {
numberOfLines = Int(estimatedSize.height / textView.font!.lineHeight)
var contentInset:UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: self.savedKbHeight, right: 0.0)
print("contentInset: \(contentInset)")
scrollView.contentInset = contentInset
scrollView.scrollIndicatorInsets = contentInset
if textView.isFirstResponder {
let fr = textView.frame
scrollView.scrollRectToVisible(fr, animated: false)
}
didExpandTextView = false
}
textView.isScrollEnabled = false
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
【问题讨论】:
-
快速测试表明此代码存在一些问题...即使使用您发布的动画,滚动内容似乎也被推到了不必要的高度。此外,当键盘显示时点击任一文本字段时,会将文本字段向上推并超出框架。 (我很惊讶你没有使用我为这个布局提供的键盘代码。)
-
我已经试过你的代码了,结果还是一样。使用您的代码,约束和动画都显示与我上面的代码相同的问题。请尝试插入一个 textview 并将其高度限制为
-
这里是使用您的代码显示结果的链接。 imgur.com/a/EklKnaw
-
如果您仍然遇到此问题,我认为问题可能是由于您正在执行的“自动垂直居中”。您可能需要采取不同的方法。
-
我还是有问题。我没有明白你所说的自动垂直居中的意思。你能用代码详细说明一下吗?
标签: ios swift uiscrollview uitextview uistackview