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!
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