I am switching from UIKit to SwiftUI and still struggle to understand some parts of it, especially the transitions between views.
I have a situation where is displayed on screen a view controller with a list, say ElementsListViewController()
, and when tapping an element I want to display a modal with a custom UI/animation: the opaque overlay would appear with an animation of the alpha value while the white modal "sheet" would appear from bottom to top.
Here is what it looks like:
With UIKit, I would use UIViewControllerAnimatedTransitioning
to do that.
Now I would like to do the same with SwiftUI, but I am lost with what to do exactly here.
I have this so far:
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ElementsList()
}
}
}
struct ElementsList: View {
@State var elements: [String] = (0..<100).map { "Element #\($0)" }
var body: some View {
List(elements, id: \.self) {
Text($0)
.onTapGesture {
// what to do here to display ModalView as I want to?
}
}
.listStyle(PlainListStyle())
}
}
struct ModalView: View {
var body: some View {
ZStack {
Color.black.opacity(0.8)
Color.white
.cornerRadius(20.0)
.padding(.top, 150)
}
.ignoresSafeArea()
}
}
What is my best option here? Thank you for your help
Well there is no built-in such flexibility say with standard .sheet, but it can be implemented custom very fast.
Here is simple demo (Xcode 13.3 / iOS 15.4)
Main part:
struct ElementsList: View {
// ...
ModalView(isPresented: $isModal) {
List(elements, id: \.self) {
struct ModalView<V: View>: View {
@Binding var isPresented: Bool
// ...
ZStack {
content()
ZStack {
VStack {
if isPresented {
Color.black.opacity(0.8)
.transition(.opacity)
}
}.animation(.easeInOut(duration: 0.25), value: isPresented)