【SwiftUI】自動スクロール機能を持つCustom TabView



## はじめに
基本的なTabViewではTabViewの活用に限界がある。

TabItemをカスタマイズし、一回タップで最初のページに戻り、2回目でスクロールを一番上に戻す機能を加える。

## 環境
Xcode 13.3.1



## Code

```swift: MainTabView
struct MainTabView: View {
    
    @EnvironmentObject var value : ValuesModel
    
    @State var showNextPage = false
    
    init(){
        UITabBar.appearance().isHidden = true
    }
    
    @State var countForScroll = 0
    @State var currentTab = "house"
    
    var body: some View {
        VStack {
            TabView(selection: $currentTab){
                HouseView(countForScroll: $countForScroll, showNextPage: $showNextPage)
                    .tag("house")
                Text("message")
                    .tag("message")
                Text("person")
                    .tag("person")
                Text("mail")
                    .tag("mail")
                
            }
            .padding(.bottom)
        }
        .safeAreaInset(edge: .bottom) {
            customtabview
        }
    }
    
    private var customtabview : some View {
        HStack(spacing: 0) {
            TabVButton(image: "house")
            TabVButton(image: "message")
            TabVButton(image: "person")
            TabVButton(image: "mail")
        }
        .background(Color.white)
    }
    
    @ViewBuilder
    func TabVButton(image: String) -> some View {
            Image(systemName: image)
                .resizable()
                .renderingMode(.template)
                .aspectRatio(contentMode: .fit)
                .frame(width: 23, height: 22)
                .foregroundColor(currentTab == image ? .red : .gray )
                .frame(maxWidth: .infinity)

                .onTapGesture {
                    
                    if currentTab == image {
                        if self.showNextPage {
                            self.showNextPage = false
                        } else {
                            self.countForScroll += 1
                        }
                    } else {
                            currentTab = image
                        
                    }
        }
    }
}
```



```swift:HouseView
struct HouseView: View {
    
    @EnvironmentObject var value : ValuesModel
    @Binding var countForScroll : Int
    @Binding var showNextPage : Bool
    

    var body: some View {
        NavigationView{
            ScrollView {
                ScrollViewReader{ ScrollViewProxy in
                    VStack{
                        
                        HStack{Spacer()}
                            .id("Empty")
                        
                        NavigationLink("", isActive: $showNextPage) {
                            NextView()
                        }
                        
                        ForEach(0 ..< 20 ) { item in
                            HStack{
                                Spacer()
                                Text("\(item)")
                                Spacer()
                            }
                            .padding()
                            .background(Color.init(white: 0.9))
                            .cornerRadius(20)
                        }
                        
                        Button {
                            self.showNextPage.toggle()
                        } label: {
                            Text("show next page")
                        }
                    }
                    .onReceive(value.$count) { XX in
                        withAnimation {
                            ScrollViewProxy.scrollTo("Empty", anchor: .top)
                        }
                    }
                    .onChange(of: countForScroll) { newValue in
                        value.count += 1
                    }
                }

            }
            .navigationBarHidden(true)
        }
        
    }
}
```

```swift:NextView
struct NextView: View {
    @State var nextPage2 = false
    var body: some View {
        VStack{
            NavigationLink("", isActive: $nextPage2) {
                Text("nextpage2")
            }
            
            Button {
                self.nextPage2.toggle()
            } label: {
                Text("nextpage2")
            }
        }
    }
}

```



```swift:ValuesModel
class ValuesModel: ObservableObject {
    
    @Published var count = 1
}

```
自動スクロールのためのcountをenvironmentObjectとしてvaluesModelで管理することで、view 移動時にcountが初期化されることを防ぎました。


### Screen
ローディングに時間がかかります。
![Sep-01-2022 21-40-36.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/027ea583-9163-8b0a-608d-05e32376cb33.gif)


他のTabを押しても元のTabのViewの状態は残っている。
現在選択中のTabItemを一回タップ　-> 最初のviewに戻る
2回目をタップ　-> Scroll を一番上に戻す


より簡単な方法や質問があればコメントください。