Ethan Brimhall
Ethan Brimhall

Reputation: 51

I created a custom tab bar in SwiftUI, but when I select a tab, it completely reloads the view. How do I prevent this

  1. I created a custom tab bar
  2. I am using a switch statement to switch between my views
  3. The problem is that the view is being reloaded everytime I switch between tabs
  4. How do I "save" the state of the view when I switch between views?

So for example, if I am in the view of the first tab and I scroll down a bit on my scrollview, and I go to the 2nd tab, and then back to the first tab, it completely reloads the view and it doesn't show that I have scrolled down the page.

The Code:

struct Home: View {

   @State var selectedIndex = 0
   @State var presented = false

   let icons = ["house", "hands.sparkles", "plus", "message", "person"]



   var body: some View {
    
    VStack{
        
        Spacer().fullScreenCover(isPresented: $presented, content: {
            Text("Create Post Here")
            Button(action: {
                presented.toggle()
            }, label: {
                Text("Close")
            })
        })
        
        switch selectedIndex{
            
        case 0:
            HomePage()
        case 1:
            NavigationView(){
                Discover()
            }
        case 2:
            LogoutForNow()
        case 3:
            LogoutForNow()
        case 4:
            NavigationView(){
                Profile2()
            }
            
        default:
            HomePage()
        }
        
        
        
        
        HStack{
            ForEach(0..<5, id: \.self){number in
                
                Spacer()
                Button(action: {
                    
                    if number == 2{
                        presented.toggle()
                    }else{
                        self.selectedIndex = number
                    }
                    
                }, label: {
                    if number == 2{
                        Image(systemName: icons[number])
                            .font(.system(size: 25, weight: .regular, design: .default))
                            .foregroundColor(.white)
                            .frame(width: 50, height: 50)
                            .background(Color.blue)
                            .cornerRadius(25)
                    }else{
                        Image(systemName: icons[number])
                            .font(.system(size: 25, weight: .regular, design: .default))
                            .foregroundColor(selectedIndex == number ? .black : Color(UIColor.lightGray))
                    }
                })
                Spacer()
            }
        }
    }
    
}

}

Upvotes: 5

Views: 1451

Answers (1)

Stoic
Stoic

Reputation: 1216

There are a few ways you could go about doing this.

Method 1: Changing Z-Index

Rather than showing either one view or another, you could keep both views being drawn at all times, but display the current, active view on top of the inactive views. You can do this by using the .zIndex() modifier.

Method 2: Using @SceneStorage (or @AppStorage)

The @SceneStorage and @AppStorage property wrappers both enable data persistence. For either one, you should keep track of the value you want to persist (such as the scroll height or something), and store it in SceneStorage/AppStorage.

@AppStorage is usually used for storing user preferences or constants, and would be the worse out of the two options, but is still possible. What you should, ideally, use is @SceneStorage. Essentially, @SceneStorage lets you store small amounts of data in the "scene", such as how far the user has scrolled. However, this data is destroyed when the scene is destroyed, such as when the user closes the app. You can find out more here

Also, if you're wondering how to store how far a user has scrolled in a ScrollView, you should use a ScrollViewReader :)

Upvotes: 5

Related Questions