布局约束动画与设备旋转同步问题求助
解决旋转设备时TextField与键盘动画同步的问题
我之前也碰到过这个棘手的场景——键盘弹出时旋转设备,TextField的约束动画总是和系统旋转动画“各走各的”,看起来特别割裂。你已经找对了方向:拿到旋转动画的参数,再把它复用在键盘相关的动画里,就能让两者完美同步。下面是具体的实现方案:
1. 先把旋转动画的参数存起来
在viewWillTransition(to size:)方法里,把系统旋转动画的时长和曲线参数保存为全局变量,这样后面处理键盘动画时能直接用:
private var rotationAnimDuration: TimeInterval = 0.0 private var rotationAnimCurve: UIView.AnimationCurve = .linear override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) // 捕获旋转动画的核心参数 rotationAnimDuration = coordinator.transitionDuration if let curve = coordinator.animationCurve { rotationAnimCurve = curve } // 旋转完成后重置参数,避免影响后续正常键盘动画 coordinator.animate(alongsideTransition: nil) { _ in self.rotationAnimDuration = 0.0 self.rotationAnimCurve = .linear } }
2. 拦截键盘通知,复用旋转动画参数
监听UIKeyboardWillChangeFrameNotification时,不要直接用键盘通知自带的动画参数,而是优先使用我们保存的旋转动画参数,确保TextField的约束动画和旋转动画完全同频:
@objc private func handleKeyboardFrameChange(_ notification: Notification) { guard let userInfo = notification.userInfo, let endFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect else { return } // 计算TextField需要调整的底部约束值 let safeBottomInset = view.safeAreaInsets.bottom let keyboardHeight = view.convert(endFrame, from: nil).height - safeBottomInset yourTextFieldBottomConstraint.constant = keyboardHeight // 选择动画参数:有旋转动画时用旋转参数,否则用键盘默认参数 let defaultAnimDuration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? TimeInterval ?? 0.25 let targetDuration = rotationAnimDuration > 0 ? rotationAnimDuration : defaultAnimDuration let defaultCurveRaw = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? Int ?? UIView.AnimationCurve.easeInOut.rawValue let targetCurve = rotationAnimDuration > 0 ? rotationAnimCurve : UIView.AnimationCurve(rawValue: defaultCurveRaw) ?? .easeInOut // 执行同步动画 UIView.animate(withDuration: targetDuration, delay: 0, options: targetCurve.animationOptions, animations: { self.view.layoutIfNeeded() }, completion: nil) } // 给AnimationCurve加个扩展,方便转成AnimationOptions extension UIView.AnimationCurve { var animationOptions: UIView.AnimationOptions { switch self { case .easeInOut: return .curveEaseInOut case .easeIn: return .curveEaseIn case .easeOut: return .curveEaseOut case .linear: return .curveLinear @unknown default: return .curveLinear } } }
3. 边界情况处理
- 如果是正常弹出键盘(没有旋转),代码会自动 fallback 到键盘通知的默认动画参数,不影响常规场景的体验;
- 旋转完成后重置参数,避免残留的旋转参数干扰后续的键盘动画。
核心思路就是让TextField的约束动画和系统旋转动画共享完全一致的时长、曲线参数,这样两者就能完美同步,实现你想要的流畅效果。
内容的提问来源于stack exchange,提问作者Sphingobium
相关产品推荐
相关产品推荐

