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

UIViewControllerRepresentable嵌套的UIScrollView容器内视图动画/过渡失效问题求助

UIViewControllerRepresentable嵌套的UIScrollView容器内视图动画/过渡失效问题求助

大家好,我最近尝试用UIViewControllerRepresentable封装了一个UIScrollView,想做一个自定义的SwiftUI滚动容器,但遇到了一个头疼的问题:当我把带过渡动画的视图嵌入这个容器里时,它们的动画完全不生效了!但同样的视图放在容器外面时,动画表现完全正常。

下面是我的测试代码,麻烦大家帮忙看看哪里出问题了?

测试视图代码

struct Demo: View {
    class ViewModel: ObservableObject {
        @Published var option1: Bool = false
        @Published var option3: Bool = false
    }
    
    @StateObject private var viewModel = ViewModel()
    @State private var option2: Bool = false
    @State private var option4: Bool = false
    
    var body: some View {
        VStack {
            VStack {
                Text("In Scroll Container")
                UIScrollContainer {
                    VStack(spacing: 0) {
                        VStack {
                            Toggle("ViewModel Option 1", isOn: $viewModel.option1.animation())
                            if viewModel.option1 {
                                Text("Option 1 is ON")
                                    .padding(.vertical, 20)
                            }
                        }
                        .padding()
                        .background(.black.opacity(0.1))
                        
                        VStack {
                            Toggle("Option 2", isOn: $option2.animation())
                            if option2 {
                                Text("Option 2 is ON")
                                    .padding(.vertical, 20)
                            }
                        }
                        .padding()
                        .background(.black.opacity(0.2))
                    }
                }
            }
            .background(.red.opacity(0.2))
            .frame(maxHeight: .infinity)
            
            VStack(spacing: 0) {
                Text("Without Container")
                VStack {
                    Toggle("ViewModel Option 3", isOn: $viewModel.option3.animation())
                    if viewModel.option3 {
                        Text("Option 3 is ON")
                            .padding(.vertical, 20)
                    }
                }
                .padding()
                .background(.black.opacity(0.1))
                
                VStack {
                    Toggle("Option 4", isOn: $option4.animation())
                    if option4 {
                        Text("Option 4 is ON")
                            .padding(.vertical, 20)
                    }
                }
                .padding()
                .background(.black.opacity(0.2))
                
                Spacer()
            }
            .background(.yellow.opacity(0.2))
            .frame(maxHeight: .infinity)
        }
    }
}

自定义滚动容器代码

struct UIScrollContainer<Content: View>: UIViewControllerRepresentable {
    let content: Content
    
    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }
    
    func makeUIViewController(context: Context) -> UIViewController {
        let scrollViewVC = UIViewController()
        scrollViewVC.view.backgroundColor = .clear
        
        let scrollView = UIScrollView()
        scrollView.backgroundColor = .clear
        
        let contentVC = UIHostingController(rootView: self.content)
        contentVC.sizingOptions = .intrinsicContentSize
        contentVC.view.backgroundColor = .clear
        contentVC.safeAreaRegions = []
        
        context.coordinator.contentVC = contentVC
        context.coordinator.scrollView = scrollView
        scrollView.delegate = context.coordinator
        
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollViewVC.view.addSubview(scrollView)
        
        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: scrollViewVC.view.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: scrollViewVC.view.bottomAnchor),
            scrollView.leadingAnchor.constraint(equalTo: scrollViewVC.view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: scrollViewVC.view.trailingAnchor)
        ])
        
        contentVC.willMove(toParent: scrollViewVC)
        scrollViewVC.addChild(contentVC)
        
        contentVC.view.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(contentVC.view)
        
        NSLayoutConstraint.activate([
            contentVC.view.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
            contentVC.view.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
            contentVC.view.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
            contentVC.view.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
            contentVC.view.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor)
        ])
        
        contentVC.didMove(toParent: scrollViewVC)
        
        return scrollViewVC
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        withTransaction(context.transaction) {
            context.coordinator.contentVC?.rootView = content
        }
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator()
    }
    
    class Coordinator: NSObject, UIScrollViewDelegate {
        var contentVC: UIHostingController<Content>?
        var scrollView: UIScrollView?
    }
}

我试过在updateUIViewController里用withTransaction来传递动画事务,但好像没起作用。有没有大佬能指点一下,这个自定义容器哪里没处理好,导致内部视图的动画失效了?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 09:09:37