fermoya / SwiftUIPager

Native Pager in SwiftUI
MIT License
1.28k stars 171 forks source link

[BUG] Can't scroll TabView with TabViewPageStyle which is nested in vertical SwiftUIPager #168

Closed quidnu closed 3 years ago

quidnu commented 3 years ago

If you nest a TabView with TabViewPageStyle inside a vertical SwiftUIPager you cannot vertically page. I'm guessing this is a problem with gesture priority (but a horizontal SwiftUIPager in a vertical SwiftUI pager does work?). Is there a workaround?

fermoya commented 3 years ago

Hi @quidnu , this isn’t a bug, this is expected. SwiftUI doesn’t offer a way to pass down the touch to other subviews. There’s a similar issue here #153 where I give a possible workaround.

Other options are to play with the modifiers that are available in Pager:

fermoya commented 3 years ago

I’m gonna close this as there’s already a similar / related issue and there’s anything to be down at the moment

fermoya commented 3 years ago

For reference, in this example EmbeddedExampleView I manage to embed a horizontal Pager into a ScrollView. Your scenario with TabView should be similar to this

quidnu commented 3 years ago

I've tried using pagingPriority without success, I've gotten a nested SwiftUIPager to work fine, I don't understand what is different with the TabView.

I'm giving up on trying to get this to work because there are too many other problems to deal with (like the fact that the tabview moves vertically when dragging) even if the paging works. But here's a minimal example illustrating the problem for completeness in case anyone else wants to try to tackle it.

` struct BarView: View {

@State var page: Int = 2
@State var data = Array(0..<5)

func pageView(_ index: Int) -> some View {

     TabView {
         ForEach(0..<3){hindex in
             Text("hello \(index):\(hindex)"
             ).frame(width:200, height:200)
               .background(index % 2 == 0 ? Color.red : Color.blue)
         }
     }.background(Color.green)
       .tabViewStyle(PageTabViewStyle())

}

var body: some View {
    Pager(page: $page,
          data: self.data,
          id: \.self,
          content: { index in
            self.pageView(index)
          })
        .sensitivity(.high)
        .vertical()
        .pagingPriority(.simultaneous)
        .swipeInteractionArea(.allAvailable)
        .onDraggingBegan({
            print("Dragging Began")
        })
 }

}

`

fermoya commented 3 years ago

not sure what you're trying to do @quidnu , but I'd definitely try to have TabView as the outer-most View and not the inner-most. There's a workaround to your problem suggested here #170

fermoya commented 3 years ago

please try to embed a Pager inside a Pager, both with pagingPriority(.simultaneous) in version 1.14.2-beta.1

struct ContentView: View {
    @State var outerPage: Int = 0
    @State var innerPages: [Int] = [0, 0, 0]

    var body: some View {
        ZStack {
            Pager(page: $outerPage, data: Array(0..<3)) { parent in
                Pager(page: $innerPages[parent], data: Array(0..<10)) { item in
                    ZStack {
                        Color.red
                        Text("\(parent)_\(item)")
                            .foregroundColor(.white)
                    }
                }
                .vertical()
                .pagingPriority(.simultaneous)
            }
            .pagingPriority(.simultaneous)
        }
    }
}
quidnu commented 3 years ago

not sure what you're trying to do @quidnu , but I'd definitely try to have TabView as the outer-most View and not the inner-most. There's a workaround to your problem suggested here #170

I want the vertical view to be the "main" or "major" scroll and the horizontal scroll (the TabView) to be the detail or "minor" scroll. I didn't notice any problem when using a nested pager instead of a TabView but I will make sure to update the package version to the latest beta as described in #170. The issue I was having was only with the TabView.

fermoya commented 3 years ago

@quidnu what I noticed from your example is that TabView was somehow "canceling" the gesture. If you implement both onDragBegan and onDragEnded in your example code you'll notice how onDragEnded was never getting called.

Try using the beta version I released this afternoon and swap TabView with another Pager, similar to what I shared. It should work

quidnu commented 3 years ago

Thanks, a nested pager does work (I hadn't noticed the animation problem initially but the new beta release does fix that).

what I noticed from your example is that TabView was somehow "canceling" the gesture. If you implement both onDragBegan and onDragEnded in your example code you'll notice how onDragEnded was never getting called.

Strange that the onDragBegan doesn't seem to be called after the first drag on a page.

Anyway I will use a nested pager. Thanks again.