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

SwiftUI中如何修改fullScreenCover的转场动画?

实现FullScreenCover左侧滑入转场

SwiftUI默认的fullScreenCover依赖UIKit底层的全屏模态转场动画,直接给目标视图添加.transition(.move(edge: .leading))不会生效——这个修饰符仅作用于SwiftUI视图树内的视图插入/移除动画,而非模态视图的展示动画。要实现左侧滑入效果,需要通过桥接UIKit自定义转场动画来实现:

步骤1:创建左侧滑入的转场动画类

import UIKit

class LeftSlideTransition: NSObject, UIViewControllerAnimatedTransitioning {
    // 设置动画时长
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.35
    }

    // 实现滑入动画逻辑
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let toViewController = transitionContext.viewController(forKey: .to) else { return }
        let containerView = transitionContext.containerView
        
        // 初始状态:视图位于屏幕左侧外
        toViewController.view.frame = CGRect(
            x: -containerView.bounds.width,
            y: 0,
            width: containerView.bounds.width,
            height: containerView.bounds.height
        )
        containerView.addSubview(toViewController.view)
        
        // 执行滑入动画
        UIView.animate(withDuration: transitionDuration(using: transitionContext)) {
            toViewController.view.frame = containerView.bounds
        } completion: { finished in
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        }
    }
}

步骤2:自定义转场代理

class CustomTransitionDelegate: NSObject, UIViewControllerTransitioningDelegate {
    // 返回自定义的转场动画实例
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return LeftSlideTransition()
    }
}

步骤3:封装SwiftUI视图为UIKit控制器

import SwiftUI

struct CustomFullScreenCover<Content: View>: UIViewControllerRepresentable {
    let content: Content
    @Binding var isPresented: Bool
    private let transitionDelegate = CustomTransitionDelegate()

    func makeUIViewController(context: Context) -> UIHostingController<Content> {
        let hostingVC = UIHostingController(rootView: content)
        hostingVC.modalPresentationStyle = .fullScreen
        hostingVC.transitioningDelegate = transitionDelegate
        return hostingVC
    }

    func updateUIViewController(_ uiViewController: UIHostingController<Content>, context: Context) {
        // 同步展示状态
        if isPresented, !uiViewController.isBeingPresented {
            context.coordinator.topVC?.present(uiViewController, animated: true)
        } else if !isPresented, !uiViewController.isBeingDismissed {
            uiViewController.dismiss(animated: true)
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator()
    }

    class Coordinator: NSObject {
        // 获取当前最上层的视图控制器
        var topVC: UIViewController? {
            UIApplication.shared.connectedScenes
                .compactMap { $0 as? UIWindowScene }
                .first?.windows
                .first { $0.isKeyWindow }?
                .rootViewController?
                .topMostViewController()
        }
    }
}

// 扩展:递归获取最上层视图控制器
extension UIViewController {
    func topMostViewController() -> UIViewController {
        if let presented = presentedViewController {
            return presented.topMostViewController()
        }
        return self
    }
}

步骤4:替换原fullScreenCover使用自定义组件

struct LoginView: View {
    @State private var isLoginSuccess = false

    var body: some View {
        Button("登录") {
            isLoginSuccess = true
        }
        // 使用自定义的全屏覆盖组件
        .background(CustomFullScreenCover(content: HomeView(), isPresented: $isLoginSuccess))
    }
}

struct HomeView: View {
    var body: some View {
        ZStack {
            Color.blue.ignoresSafeArea()
            Text("首页")
                .font(.largeTitle)
                .foregroundColor(.white)
        }
    }
}

点击登录按钮后,HomeView就会从左侧滑入全屏展示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 02:05:20