Search code examples
flutterswiftuiscroll

Flutter(SingleChildScrollView) not scrolling inside a SwiftUI view


I'm working on a project where we're transitioning from a native SwiftUI application to a Flutter-based one. To bridge the gap, we are maintaining both SwiftUI and Flutter projects concurrently.

Project Setup: We've developed some features in Flutter. The Flutter project is compiled into an .xcframework. This .xcframework is then imported into our SwiftUI project. The Issue: One of the Flutter views contains content within a SingleChildScrollView. The scrolling works perfectly when I run the Flutter project directly, either on a simulator or a physical device.

However, when I integrate this Flutter view into my SwiftUI project and present it as a sheet, the view does not scroll as expected. The content remains static, and the scrolling behavior is completely lost.

        .sheet(item: $detailsUrl) { _ in
            /// This view adds our flutter view 
            InformationDetailView(url: $detailsUrl)
        }
//// ------- Above part present the view as a sheet ------------ 


import Foundation
import SwiftUI
import CommonUI
import Flutter
import FlutterPluginRegistrant

/// Shows a flutter view with a close icon - based on a detail url containing
/// a specific JSON
internal struct InformationDetailView: View {
    @Binding internal var url: String?

    internal var body: some View {
        NavigationView {
            if let url {
                InformationDetailFlutterView(url: url)
                    .navigationBarItems(
                        leading:
                            Button {
                                self.url = nil
                            } label: {
                                R.image.abort.image
                                    .resizable()
                                    .aspectRatio(contentMode: .fit)
                                    .liebherrShadow()
                                    .frame(width: 24, height: 24)
                            }
                            .frame(width: 40, height: 40)
                            .contentShape(Rectangle())
                    )
//                    .simultaneousGesture(DragGesture(minimumDistance: 0), including: .all)
                    .modifier(NavigationBarModifier(isTransparent: true))
            }
        }
        .modifier(InteractiveDismissDisabledModifier())
    }
}

/// Loads the flutter engine with a specific url
internal struct InformationDetailFlutterView: UIViewControllerRepresentable {
    @StateObject var flutterDependencies: InformationDetailDependencies

    /// Initialized with a url to the details object
    internal init(url: String) {
        self._flutterDependencies = StateObject(wrappedValue: InformationDetailDependencies(withUrl: url))
    }

    /// Creates the view from a view controller
    internal func makeUIViewController(context: Context) -> some UIViewController {
        /// Create a FlutterViewController from a pre-warmed FlutterEngine
        let flutterViewController = FlutterViewController(
            engine: flutterDependencies.flutterEngine,
            nibName: nil,
            bundle: nil
        )
        return flutterViewController
    }

    /// Not needed currently
    internal func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
}

/// Instantiates the engine with a given url
internal class InformationDetailDependencies: ObservableObject {
    let flutterEngine = FlutterEngine(name: "informationdetails engine")
    init(withUrl url: String) {
        if let percentUrl = url.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) {
            /// Runs at the specific route
            flutterEngine.run(withEntrypoint: nil,
                              initialRoute: "/information-details/?url=\(percentUrl)")
            /// Connects plugins with iOS platform code to this app.
            GeneratedPluginRegistrant.register(with: self.flutterEngine)
        }
    }
}

What I've Tried: Verified that the scrolling works in the standalone Flutter app. Ensured the .xcframework was correctly integrated into the SwiftUI project. I experimented with different presentation styles in SwiftUI, but the issue persists. Question: Has anyone encountered similar issues when embedding Flutter views inside a SwiftUI project? If so, how did you resolve the scrolling problem?

Any insights or suggestions would be greatly appreciated!


Solution

  • We can't use .sheet() presentation in such a case. It will have a conflict on Gesture with SwiftUI interactiveDismiss and scroll in the Flutter view side. You can disable the interactive dismiss .interactiveDismissDisabled() but still it won't solve the problem. Instead of .sheet(), .fullScreenCover() will solve the problem for us. Update: Still now, I am looking for a proper solution so that I can use Flutter element as a sheet() presentation