Вы должны использовать UIScrollView
, а не UIView
. ScrollView будет иметь contentView
, который является ничем иным, как UIView
.
К этому UIView
(я бы лучше сказал contentView) вы добавляете свои текстовые поля.
Вот так это будет выглядеть в раскадровке с ограничениями.
UIScrollView верхнее и нижнее пространство выровнены с верхним и нижним указателем макета. Остальные ограничения просты.
В приведенном ниже коде мы проверяем, открыта ли уже клавиатура или нет. Если значения edgeinsets равны нулю, т.е. нижняя вставка содержимого равна нулю, это означает, что клавиатура будет открыта. Здесь мы удостоверимся, что вставка снизу теперь изменится, например, на 280,0, т. Е. Представление содержимого будет перемещено на 280 пунктов к верхнему краю.
Когда клавиатура закрыта, мы перемещаем contentInset.bottom
назад на 0 пунктов от нижней части представления содержимого,
func bindToKeyboard() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}
//Set default to zero, when keyboard opens it changes to a non zero value. When keyboard closes it is set back to the correct value.
var scrollContentInset = UIEdgeInsets.zero
@objc func keyboardWillChange(notification: NSNotification) {
let duration = notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as! UInt
let endingFrame = (notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIView.KeyframeAnimationOptions(rawValue: curve), animations: {
if self.scrollContentInset.bottom == 0 {
let adjustmentHeight = (endingFrame.height + 20) * (1)
self.scrollView.contentInset.bottom += adjustmentHeight
self.scrollView.scrollIndicatorInsets.bottom += adjustmentHeight
} else{
let adjustmentHeight = (endingFrame.height + 20) * (-1)
self.scrollView.contentInset.bottom += adjustmentHeight
self.scrollView.scrollIndicatorInsets.bottom += adjustmentHeight
}
self.scrollContentInset = self.scrollView.contentInset
}, completion: nil)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
iOS keyboardWillChange:
вызывается несколько раз. Таким образом, логика клавиатуры здесь немного изменилась. Перед открытием клавиатуры Y - это высота экрана UIS, при открытии клавиатуры Y перемещается вверх в направлении своей ориентации (верхний левый угол равен 0,0). Это помогает обнаружить открытие клавиатуры.
Когда клавиатура закрывается, иногда из-за программной клавиши (cmd + K
) или из-за клавиши возврата высота клавиатуры отличается в этих случаях. Конечный кадр имеет высоту 54 точки в случае (cmd + K
), в то время как начальный кадр имеет высоту 355,0. Поскольку клавиатура была открыта с высоты 355,0, она должна смещаться на ту же величину Поэтому я использую здесь максимальную высоту startFrame и EndFrame.
В случае, если клавиатура открыта в режиме программной клавиатуры, Y startFrame
и endFrame
будут одинаковыми, поэтому в этом случае contentInset не изменяется.
Надеюсь, это поможет решить проблему с клавиатурой.
@objc func keyboardWillChange(notification: NSNotification) {
let duration = notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as! UInt
let startFrame = (notification.userInfo![UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let endingFrame = (notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIView.KeyframeAnimationOptions(rawValue: curve), animations: {
if startFrame.minY > endingFrame.minY {
/*
*Keyboard opening
*/
let adjustmentHeight = CGFloat.maximum(startFrame.height, endingFrame.height)
self.scrollView.contentInset.bottom = adjustmentHeight
self.scrollView.scrollIndicatorInsets.bottom = adjustmentHeight
} else if startFrame.minY < endingFrame.minY{
/*
*Keyboard Closing
*/
let adjustmentHeight = CGFloat.maximum(endingFrame.height, startFrame.height) * (-1)
self.scrollView.contentInset.bottom += adjustmentHeight
self.scrollView.scrollIndicatorInsets.bottom += adjustmentHeight
}
}, completion: nil)
}
Еще одна вещь, которую я нашел здесь, это то, что в ландшафтном режиме (landscapeRight
) высота начального кадра составляла 277,0, а высота конечного кадра составляла 209,0. и когда мы свернули клавиатуру, это было с 209. Это происходит, когда устройство находилось в режиме potrait, а затем вы открывали клавиатуру в правостороннем режиме.
Так что вы можете захотеть, чтобы высота регулировки при открытии клавиатуры была конечной.
if startFrame.minY > endingFrame.minY {
let adjustmentHeight = endingFrame.height
.........
}