LoginSignup
0
1

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-09-02

はじめに

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

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

環境

Xcode 13.3.1

Code

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
                        
                    }
        }
    }
}
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)
        }
        
    }
}
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")
            }
        }
    }
}

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

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

Screen

ローディングに時間がかかります。
Sep-01-2022 21-40-36.gif

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

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

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1