0

I'm trying to create popup in SwiftUI and faced some problems. Some of them like a different .transition on the same View solved by tips from SO, but some still hard to resolve.

There are few problems in code example:

  1. Popup view animate incorrect when you first time call it. It's just appear but not coming from the bottom
  2. It seems like two types of .transition applying to popup, but it should be one to each part of it
  3. Data on the back View start to glitching when popup appears and disappears
  4. And finally popup doesn't come from the bottom and disappears before coming to the edge

Code example

struct SOAnimation: View {
    @State var selectedImage = "camera.filters"
    @State var showPopup = false
    @State var showView = true
    var body: some View {
        ZStack(alignment: .top) {
            VStack {
                Text("Image").font(.largeTitle).fontWeight(.bold)
                ZStack {
                    Image(systemName: "circle.fill")
                        .resizable()
                        .frame(width: 81, height: 81)
                        .foregroundColor(Color.blue.opacity(0.2))
                    Image(systemName: selectedImage)
                        .resizable()
                        .frame(width: 44, height: 44)
                } .onTapGesture {
                    withAnimation(.spring()) {
                        showPopup = true
                    }
                }
                VStack(alignment: .leading) {
                    ForEach(1..<25) { _ in
                        Text(UUID().uuidString)
                            .fontWeight(.semibold)
                    }
                }
                Spacer()
            }
            if showPopup { Popup(selectedImage: $selectedImage, showPopup: $showPopup)}
        }
    }
}

struct Popup: View {
    @Binding var selectedImage: String
    @Binding var showPopup: Bool
    private let columns: [GridItem] = Array(repeating: .init(.flexible()), count: 4)
    private let images = ["camera.filters", "seal", "circle", "oval", "app", "diamond", "octagon", "play", "pause", "forward", "goforward", "wave.3.forward", "skew"]
    var body: some View {
        ZStack {
            if showPopup { // Logic for different types of transition
                Color.black.opacity(0.5)
                    .onTapGesture { withAnimation(.spring()) { showPopup = false }}
                    .ignoresSafeArea(edges: .all)
                    .transition(.opacity)
            }
            if showPopup { // Logic for different types of transition
                LazyVGrid(columns: columns, alignment: .center, spacing: 20) {
                    ForEach(images, id: \.self) { image in
                        Image(systemName: image)
                            .resizable()
                            .frame(width: 30, height: 30)
                            .onTapGesture {
                                selectedImage = image
                                withAnimation(.spring()) { showPopup = false }
                            }
                    }
                }
                .padding()
                .onTapGesture {}
                .background(Color.white)
                .cornerRadius(20)
                .transition(.move(edge: .bottom))
                .padding(.horizontal)
            }
        }
    }
}

Code example result:

enter image description here

Expected result:

enter image description here

Nizami
  • 728
  • 1
  • 6
  • 24

1 Answers1

0

If I'm guessing, the undefined behavior comes from the LazyVGrid, you can achieve the same layout with VStacks and HStacks.

I also think it would be better to create a viewModifier and an extension for the popup instead of using ZStack's. I followed this article and use a similar popup in my app without any problems.

Thel
  • 396
  • 2
  • 8