UIView 动画在键盘通知后不起作用



当iOS设备旋转且键盘打开时,NotificationCenter会发送UIKeyboardWillChangeFrame通知。我正在尝试在这一点上启动自定义动画。它不起作用。

我正在尝试启动布局约束动画,但我无法使用任何自定义动画持续时间,因为它以某种方式被系统覆盖。我将始终获得与键盘向上/向下移动动画相匹配的恒定持续时间。在这种情况下,我如何使用自己的动画持续时间。

下面是我所需行为的代码示例:

@objc func keyboardWillChange(_ notification: NSNotification) {
let keyboardFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue

self.textFieldBottomContstrain.constant = -keyboardFrame.height
UIView.animate(withDuration: myOwnDuration) {
self.view.layoutIfNeeded()
}
}

更新

经过一些测试,我找到了一个非常简单的解决方案,尽管对我来说感觉有点笨拙。

但无论如何,在 UIView.animate-block 之前只添加两行代码似乎可以重置自动动画参数,我自己的参数再次工作。这是我的工作补充:

UIView.setAnimationsEnabled(false)
UIView.setAnimationsEnabled(true)

更新 2

马特提供的最佳解决方案。有一种正确的方法可以覆盖运行时设置的原始动画持续时间:https://developer.apple.com/documentation/uikit/uiviewanimationoptions/1622434-overrideinheritedduration

这里的问题是,当调用keyboardWillChange时,您已经处于一个看不到的动画块中,该动画块由运行时提供,用于对键盘的移动进行动画处理。因此:

  • 不需要UIView.animate,因为你在这里所做的任何可动画的东西都已经被动画化了。

  • 如果你UIView.animate,你的duration将被忽略,因为它是从周围的隐式动画块继承的——除非你添加option来关闭该继承:https://developer.apple.com/documentation/uikit/uiviewanimationoptions/1622434-overrideinheritedduration

  • 你不应该碰self.view的位置;这不是你的观点。如果您需要在键盘存在时滑动界面,请self.view提供一个完整的子视图并滑动它。

试试这段代码。

UIView.animate(withDuration: 0.3, animations: {
self.view.layoutIfNeeded();
self.view.layoutSubviews()
}, completion: {(value: Bool) in
});

我可以为您提供这种方法。

1) 添加结构:

struct HeightStruct {
var height: CGFloat
}

2) 添加变量:

var heightStruct: HeightStruct = .init(height: 0)

3)观察者法:

@objc func keyboardWillShow(_ notification: Notification) {
if let keyboardFrame: NSValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRectangle = keyboardFrame.cgRectValue
let keyboardHeight = keyboardRectangle.height
DispatchQueue.main.async {
self.heightStruct.height = keyboardHeight
self.changeTextFieldPosition()
}
}
}

4)添加changeTextFieldPosition方法:

func changeTextFieldPosition() {
UIView.animate(withDuration: 5.0) {
self. textFieldBottomContstrain.constant = - self.heightStruct.height
self.view.layoutIfNeeded()
}
}

它看起来很丑,但它有效。

1. 注册键盘 在视图中隐藏和显示通知DidLoad()

NotificationCenter.default.addObserver(self, selector: 
#selector(keyBoardWillShow(notification:)), name: 
.UIKeyboardWillShow , object: nil)
NotificationCenter.default.addObserver(self, selector: 
#selector(keyBoardWillHide(notification:)), name: .UIKeyboardWillHide 
, object: nil)

2.键盘隐藏显示时调用

@objc func keyBoardWillShow(notification: NSNotification){
adjustInsetForKeyBoards(show: true, notification: notification)
}
@objc func keyBoardWillHide(notification: NSNotification){
adjustInsetForKeyBoards(show: false, notification: notification)
}

3.使用动画显示和隐藏键盘的逻辑

func adjustInsetForKeyBoards(show: Bool, notification: NSNotification){
let userInfo = notification.userInfo ?? [:]
let keyboardFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
UIView.animate(
withDuration: 1.0,
animations: {
let adjustment = (keyboardFrame.height * (show ? 1 : -1)) + 20
self.scrollView.contentInset.bottom += adjustment
self.scrollView.scrollIndicatorInsets.bottom += adjustment
},
completion: nil)
}

希望这对您有用。

最新更新