SwiftUI How to gain access to ScrollViewReader's proxy when swiping TabView

Viewed 297

Currently, I created a custom navigation where selecting individual tabs (Info, Pizza, etc), it'll swipe me to a new view. Basically a UIKit equivalent of UIPageViewController.

Something different that i did is that when a selecting a section, it will also animate the scrollView to center the text. So for example, if i select the "Pasta" section, it swipe me to the correct view and center the "Pasta" text in the scrollView. To implement that, I embed a ScrollViewReader within ScrollView to gain access to proxy and everytime i select the section, i call proxy.scrollTo to scroll to proper index. But How does TabView gain access to ScrollView's proxy? So now, when I swipe to new view, the text of next page gets selected, but scrollView wont scroll to index and center it.

Is there some way to notify view if TabView is swiped? So I can call scrollTo?

struct CustomNavigationView: View {
@State var activeIndex = 0
var body: some View {
    
    VStack(spacing: 0) {
        AppBar(index: self.$activeIndex)

        TabView(selection: self.$activeIndex,
                content:  {
                    First()
                        .tag(0)
                    RecommendationPage()
                        .tag(1)
                    NewView(text: "Third", color: Color.orange)
                        .tag(2)
                })

            ///Allows the swipe to happen
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))  
    }
    .animation(.default)
    .edgesIgnoringSafeArea(.all)
  }
}


struct AppBar: View {
@Binding var index: Int

var sections = ["Episode", "Related Shows", "About", "Info", "Pizza", "Hamburger", "Pasta", "I dont even know"] 

var body: some View {
    VStack(alignment: .leading) {
        
        Text("Home")
            ...
        
         ScrollView(.horizontal, showsIndicators: false, content: {
            ScrollViewReader { proxy in
                
                VStack(alignment: .leading) {
                    //Underline bar
                    ZStack(alignment: .leading) {
                        ...
                    }
                    
                    ///Sections
                    HStack(spacing: tabsSpacing) {
                        ForEach(0..<sections.count) { i in
                            Button(action: {
                                self.index = i
                                
                                withAnimation(.linear) {
                                    
                                    ///This checks ensures that when we select last 2 items, scrollView doesnt try to align selectedIndex to middle
                                    if i < sections.count - 2 {
                                        proxy.scrollTo(i, anchor: .center)
                                    } else if i == sections.count - 2 {
                                        proxy.scrollTo(i)
                                    } else {
                                        proxy.scrollTo(i, anchor: .trailing)
                                    }
                                }
                                
                            }, label: {
                                Text(sections[i])
                                   ...
                            })
                            .id(i)
                        }
                    }   
                }
            }
        })

section as a scrollView

1 Answers
Related