You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Segue跳转时全局隐藏键盘过渡动画的实现方法咨询

嘿,这个注册流程里的键盘跳转动画问题我太懂了,之前做用户引导页的时候也被这个小细节折腾过,给你几个从局部到全局的解决方案,按需选就行:

方案一:局部处理(针对单个Segue)

如果只是特定几个Segue需要处理,直接在源ViewController和目标VC里加几行代码就行:

  1. 在源VC的prepare(for:sender:)方法里,禁用动画收起当前键盘:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    super.prepare(for: segue, sender: sender)
    // 禁用动画收起键盘
    UIView.performWithoutAnimation {
        self.view.endEditing(true)
    }
}
  1. 在目标VC的viewWillAppear(_:)里,同样禁用动画让目标文本框成为第一响应者:
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // 直接让目标文本框获取焦点,无动画
    UIView.performWithoutAnimation {
        self.targetTextField.becomeFirstResponder()
    }
}

这样两个操作都跳过了动画,用户看起来就像键盘直接“移”到了新页面的输入框上,没有关了又开的突兀感。

方案二:全局处理(所有Segue自动生效)

如果整个APP里有很多这种场景,不想每个VC都写重复代码,就用全局扩展+通知监听的方式,一劳永逸:

第一步:给UIWindow加个转场状态标记

先扩展UIWindow,用来记录当前是否正在进行ViewController转场:

import UIKit

extension UIWindow {
    private struct AssociatedKeys {
        static var isTransitioning = "isTransitioning"
    }
    
    var isTransitioning: Bool {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.isTransitioning) as? Bool ?? false
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.isTransitioning, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

第二步:监听转场通知,标记转场状态

在AppDelegate或者SceneDelegate里注册通知,记录转场的开始和结束:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // 监听转场开始
    NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "UIViewControllerTransitionCoordinatorDidBeginAnimation"), object: nil, queue: .main) { _ in
        UIApplication.shared.keyWindow?.isTransitioning = true
    }
    
    // 监听转场结束
    NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "UIViewControllerTransitionCoordinatorDidEndAnimation"), object: nil, queue: .main) { _ in
        UIApplication.shared.keyWindow?.isTransitioning = false
    }
    
    // 监听键盘隐藏通知,取消转场时的键盘动画
    NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: .main) { notification in
        guard let window = UIApplication.shared.keyWindow, window.isTransitioning else { return }
        // 把键盘隐藏动画时长设为0,取消动画
        notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] = 0
        notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] = UIView.AnimationCurve.linear.rawValue
    }
    
    return true
}

第三步:全局让目标VC的输入框自动获取焦点(可选)

如果你的注册流程里每个VC的输入框都需要自动成为第一响应者,可以给UIViewController加个扩展,统一处理:

extension UIViewController {
    open override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // 找到当前VC里的第一个UITextField,自动获取焦点(无动画)
        if let firstTextField = view.subviews.first(where: { $0 is UITextField }) as? UITextField {
            UIView.performWithoutAnimation {
                firstTextField.becomeFirstResponder()
            }
        }
    }
}

当然你也可以根据自己的需求调整,比如指定某个tag的文本框,或者用IBOutlet关联的方式。

注意事项

  • 如果你用的是导航控制器的push/pop,方案一和方案二都能生效;
  • 方案二里的通知名称UIViewControllerTransitionCoordinatorDidBeginAnimation是系统内部的通知,虽然不是公开API,但实际使用中很稳定;
  • 如果你的APP支持多场景(iPad分屏),记得把keyWindow换成当前场景的window。

内容的提问来源于stack exchange,提问作者thelearner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:38:02