[英]Why does the whole view jerk up when the keyboard hides?
调用keyboardWillHideFunction时,从viewController向上拖动整个视图。 以下是发生探针的视频。
以下是我用来控制键盘通知的代码。 我尝试过尝试动画时间和布局约束,但是我还无法获得更多。 关于如何解决它的任何建议,谢谢。
基于建议的可编辑代码-我已经尝试按照建议的那样为布局约束创建变量,但是问题仍然存在,为什么?
import UIKit
import Foundation
extension UIView {
func currentFirstResponder() -> UIResponder? {
if self.isFirstResponder {
return self
}
for view in self.subviews {
if let responder = view.currentFirstResponder() {
return responder
}
}
return nil
}
}
extension Notification.Name{
static let showKeyboard = Notification.Name("showKeyboard")
}
class KeyboardSlider: NSObject {
// variables to hold and process information from the view using this class
weak var view: UIView?
var searchBarTopTags:SearchBarTopTagsViewController?
var amountToShiftBy:CGFloat!
var originalFrame:CGRect!
var previewController:PreviewController!
@objc func keyboardWillShow(notification: NSNotification) {
self.searchBarTopTags?.myViewBottomLayoutConstraint.constant = -self.getKeyboardHeight(notification as! Notification) + previewController.view.safeAreaInsets.bottom
UIView.animate(withDuration: 0, animations: {
self.view?.layoutIfNeeded()
self.searchBarTopTags?.myView.layoutIfNeeded()
})
}
@objc func keyboardWillHide(notification:NSNotification){
self.searchBarTopTags?.myViewBottomLayoutConstraint.constant = 0
UIView.animate(withDuration: 0, animations: {
self.view?.layoutIfNeeded()
self.searchBarTopTags?.myView.layoutIfNeeded()
})
}
func getKeyboardHeight(_ notification:Notification) -> CGFloat {
// get exact height of keyboard on all devices and convert to float value to return for use
let userInfo = notification.userInfo
let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue
return keyboardSize.cgRectValue.height
}
func subscribeToKeyboardNotifications(view: UIView) {
// assigning view to class' counterpart
self.view = view
// when UIKeyboardWillShow do keyboardWillShow function
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
}
func subscribeToKeyboardNotifications(view: UIView, previewController:PreviewController? = nil) {
// assigning view to class' counterpart
self.view = view
self.searchBarTopTags = previewController?.searchBarTopTags
self.previewController = previewController
// when UIKeyboardWillShow do keyboardWillShow function
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: .UIKeyboardWillHide, object: nil)
}
func unsubscribeFromKeyboardNotifications() {
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
}
}
原始代码:
import UIKit
import Foundation
extension UIView {
func currentFirstResponder() -> UIResponder? {
if self.isFirstResponder {
return self
}
for view in self.subviews {
if let responder = view.currentFirstResponder() {
return responder
}
}
return nil
}
}
extension Notification.Name{
static let showKeyboard = Notification.Name("showKeyboard")
}
class KeyboardSlider: NSObject {
// variables to hold and process information from the view using this class
weak var view: UIView?
var searchBarTopTags:SearchBarTopTagsViewController?
var amountToShiftBy:CGFloat!
var originalFrame:CGRect!
@objc func keyboardWillShow(notification: NSNotification) {
self.originalFrame = self.searchBarTopTags?.myView.frame
self.amountToShiftBy = (self.searchBarTopTags?.view.frame.maxY)! - self.getKeyboardHeight(notification as! Notification) - (self.searchBarTopTags?.myView.frame.height)!
self.amountToShiftBy = (searchBarTopTags?.view.bounds.height)! - self.getKeyboardHeight(notification as! Notification) - (searchBarTopTags?.myView.bounds.height)!
self.searchBarTopTags?.myView.bottomAnchor.constraint(equalTo: (self.searchBarTopTags?.view.bottomAnchor)!, constant: -self.amountToShiftBy).isActive = true
UIView.animate(withDuration: 0, animations: {
self.view?.layoutIfNeeded()
self.searchBarTopTags?.view.layoutIfNeeded()
self.searchBarTopTags?.myView.layoutIfNeeded() })
}
@objc func keyboardWillHide(notification:NSNotification){
self.searchBarTopTags?.myView.bottomAnchor.constraint(equalTo: (self.searchBarTopTags?.view.bottomAnchor)!, constant: 0).isActive = true
UIView.animate(withDuration: 0, animations: {
self.view?.layoutIfNeeded()
self.searchBarTopTags?.view.layoutIfNeeded()
self.searchBarTopTags?.myView.layoutIfNeeded()
})
}
func getKeyboardHeight(_ notification:Notification) -> CGFloat {
// get exact height of keyboard on all devices and convert to float value to return for use
let userInfo = notification.userInfo
let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue
return keyboardSize.cgRectValue.height
}
func subscribeToKeyboardNotifications(view: UIView) {
// assigning view to class' counterpart
self.view = view
// when UIKeyboardWillShow do keyboardWillShow function
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
}
func subscribeToKeyboardNotifications(view: UIView, seachBarTopTagsVC:SearchBarTopTagsViewController? = nil) {
// assigning view to class' counterpart
self.view = view
self.searchBarTopTags = seachBarTopTagsVC
// when UIKeyboardWillShow do keyboardWillShow function
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: .UIKeyboardWillHide, object: nil)
}
func unsubscribeFromKeyboardNotifications() {
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
}
}
keyboardWillShow
内将显示
self.searchBarTopTags?.myView.bottomAnchor.constraint(equalTo: (self.searchBarTopTags?.view.bottomAnchor)!, constant: -self.amountToShiftBy).isActive = true
并在keyboardWillHide
内keyboardWillHide
self.searchBarTopTags?.myView.bottomAnchor.constraint(equalTo: (self.searchBarTopTags?.view.bottomAnchor)!, constant: 0).isActive = true
当然这会在键盘隐藏/显示时引起冲突,您只需要在viewDidLoad
创建一次底部约束,然后在这些方法中使用常量值就可以了,就像这样
var bottomConstraint:NSLayoutConstraint!
//
bottomConstraint = self.searchBarTopTags?.myView.bottomAnchor.constraint(equalTo: (self.searchBarTopTags?.view.bottomAnchor)!, constant: 0)
bottomConstraint.isActive = true
//
@objc func keyboardWillShow(notification: NSNotification) {
// other code
bottomConstraint.constant = -self.amountToShiftBy
}
@objc func keyboardWillHide(notification: NSNotification) {
bottomConstraint.constant = 0
// other code
}
每次调用以下行时,都会添加一个新的约束:
self.searchBarTopTags?.myView.bottomAnchor.constraint(equalTo: (self.searchBarTopTags?.view.bottomAnchor)!, constant: -self.amountToShiftBy).isActive = true
您需要添加对约束的引用,只需更改其常数即可。
let constraint = self.searchBarTopTags?.myView.bottomAnchor.constraint...
contraint.constant = ...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.