fermoya / SwiftUIPager

Native Pager in SwiftUI
MIT License
1.29k stars 172 forks source link

[BUG] The pager view behind the navigation bar #119

Closed anhtuanqn1002 closed 4 years ago

anhtuanqn1002 commented 4 years ago

Describe the bug The pager view behind the navigation bar

To Reproduce

Pager(page: $currentPage, data: data, id: \.self) { index in
      List(self.currentList) { info in
        StandardInfoRow(info: info)
      }
    }

Expected behavior The navigation bar does not overlap the pager view Screenshots / Videos swiftuipager

Environment:

fermoya commented 4 years ago

Hi @anhtuanqn1002 ,

List by default will try to expand to the edges whereas its container (Pager) doesn't. This is something that happens in SwiftUI and I'm not very sure why.

Here's a solution:

Pager(...) {
    List(...) {
        // Row
    }
}
.edgesIgnoringSafeArea(.all)

See the differences: https://media.giphy.com/media/SWi85VRVkJw7FYd5Nk/source.gif

struct ContentView: View {

    @State var tab: Int = 0
    @State var currentPage = 0
    var data = Array(1...20)

    var body: some View {
        NavigationView {
            Pager(page: $currentPage,
                  data: data,
                  id: \.self) { index in
                List(data, id: \.self) { info in
                    Text("\(info)")
                }
            }
            .edgesIgnoringSafeArea(.all)
            .navigationBarTitle("SwiftUIPager", displayMode: .inline)
        }
    }    
}
anhtuanqn1002 commented 4 years ago

Hi @fermoya , Thank you for your reply. When I switch to the present mode, everything looks fine. This issue only occurs when I push a new view from a NavigationView. I don't understand why and I think something went wrong in SwiftUI.

I also have 2 questions:

  1. Did the content view of the pager always align to the center?
  2. Will the data be reloaded every time I switch views? Example: Currently, items of List 1 in the middle or bottom, I switched to List 2 and then back to List 1, items of List 1 have been reloaded.
fermoya commented 4 years ago

Hi @anhtuanqn1002 ,

Can you modify the given example I shared in my previous comment so that I see the issue?

Answering your questions:

  1. Depends on what you mean by alignment you can use alignment or itemAspectRatio(_, alignment:)
  2. Elements aren’t really recreated but the content view builder is called on animation (swiping) to recalculate the position of the items. Pager is basically a stack wrapping a ForEach. When the offset changes (on dragging), SwiftUI will call the content builder to get the new offset of the items but items aren’t recreated
fermoya commented 4 years ago

@anhtuanqn1002 same difference if it's pushed, presented or just the entry screen. Please use edgesIgnoreSafeArea(.all) // or just .top.

Please, check out: https://media.giphy.com/media/SYiqEF8g3uni957VIG/source.gif

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink("Pushed Content", destination: PushedContent())
        }
    }
}

struct PushedContent: View {
    @State var currentPage = 0
    var data = Array(1...20)

    var body: some View {
        Pager(page: $currentPage,
              data: data,
              id: \.self) { index in
            List(data, id: \.self) { info in
                Text("\(info)")
            }
        }
        .edgesIgnoringSafeArea(.all)
        .navigationBarTitle("SwiftUIPager", displayMode: .inline)
    }
}

Feel free to re-open, but please share any reduced complete (that is, it compiles) sample code that I can put in Xcode to execute and see the problem, same as I've done in my previous comments.