0

I am working on this audio player with multiple view components in it. I added a way to hide/show the top view and the bottom view when we click anywhere in the middle view.

Before it was working fine, but recently when I tried again, it only dismiss it and doesn't trigger the onTapGesture again.

I believe the only difference with before is that the view is presented instead of pushed in a view controller.

I have tried to use a custom gesture with a TapGesture() on onEnded() but the same result. I also tried to add a Rectangle shape like said [here][1].

struct PlayerView: View {
    @ObservedObject private var playerState = PlayerState()
    @Binding var isPlayerReduced: Bool

    private let interfaceColor: Color = .gray//.black
    private let interfaceOpacity: Double = 0.9
    private let interfaceAnimationDuration: Double = 0.4

    var body: some View {
        ZStack(content: {
            GeometryReader(content: { geometry in
                VStack(content: {
                    if !self.playerState.isInterfaceHidden {
                        TopPlayerView(playerState: self.playerState,
                                      isPlayerReduced: self.$isPlayerReduced)
                            .transition(.opacity)
                            .background(self.interfaceColor.opacity(self.interfaceOpacity))
                    }
                    MiddlePlayerView(skipIntro: self.$playerState.skipIntro)
                        // Allow to spread the background zone for click purposes
                        .background(Color.clear)
                        // I want to have the middle under my TopPlayer and my BottomPlayer
                        .zIndex(-1)
                        .onTapGesture(perform: {
                            withAnimation(.easeInOut(duration: self.interfaceAnimationDuration)) {
                                self.playerState.isInterfaceHidden.toggle()
                            }
                        })
                    //                            .gesture(TapGesture()
                    //                                .onEnded({ _ in
                    //                                }))
                    if !self.playerState.isInterfaceHidden {
                        BottomPlayerView(playerState: self.playerState)
                            .padding(.bottom, geometry.safeAreaInsets.bottom)
                            .transition(.opacity)
                            .background(self.interfaceColor.opacity(self.interfaceOpacity))
                    }
                })
            })
        })
            .background(Color.black)
            .edgesIgnoringSafeArea(.all)
            .navigationBarTitle("")
            .navigationBarHidden(true)
    }
}

I am kind of out of ideas here, any help is welcomed! thank you!

Oleg G.
  • 550
  • 5
  • 25
  • If your middle view is *under* others then once both of top are non-transparent (at any value) below one does not get hits. To say something more definitely it's needed testable code to reproduce. – Asperi Aug 12 '20 at 17:32
  • Oh I see, let me check this out, I will update if I find anything! – Oleg G. Aug 12 '20 at 17:43
  • Oh but I tried without the zIndex, and it is the same issue. I put a red background to be able to see where the view move. – Oleg G. Aug 12 '20 at 17:44
  • The views are in a VStack, so they are not mixing on top of each other. Then when it dismiss, the views doesn't expand, so the middle view stays on top. – Oleg G. Aug 12 '20 at 17:48

1 Answers1

0

Alright, so after touching everything possible in this code. I ended up making it work. The difference is where I put the padding to my views. I switch the paddings to the VStack instead of my views in the VStack. It seems to work now.

I post below the working code.

var body: some View {
        ZStack(alignment: .center, content: {
            GeometryReader(content: { geometry in
                VStack(content: {
                    self.topMarker()
                    if !self.playerState.isInterfaceHidden {
                        TopPlayerView(playerState: self.playerState,
                                      isPlayerReduced: self.$isPlayerReduced)
                            .transition(.opacity)
                            .background(self.interfaceColor.opacity(self.interfaceOpacity))
                    }
                    MiddlePlayerView(skipIntro: self.$playerState.skipIntro)
                        // Allow to spread the background zone for click purposes
                        .background(Color.white.opacity(0.00000001))
                        // I want to have the middle under my TopPlayer and my BottomPlayer
                        .zIndex(-1)
                        .onTapGesture(perform: {
                            withAnimation(.easeInOut(duration: self.interfaceAnimationDuration)) {
                                self.playerState.isInterfaceHidden.toggle()
                            }
                        })
                    if !self.playerState.isInterfaceHidden {
                        BottomPlayerView(playerState: self.playerState)
                            .transition(.opacity)
                            .background(self.interfaceColor.opacity(self.interfaceOpacity))
                    }
                })
                    .padding(.top, 8)
                    .padding(.bottom, geometry.safeAreaInsets.bottom)
            })
        })
            .background(Color.black)
            .edgesIgnoringSafeArea(.all)
            .navigationBarTitle("")
            .navigationBarHidden(true)
    }

To be honest, I have no idea what would be the difference here... Even in the view debugger there is no difference..

Oleg G.
  • 550
  • 5
  • 25