'TabView animation glitch

Get that strange glitch and can't fix it. Source of problem - TabView and changing size of child views with animation. Changing UITabbar appearance not helped. Changing safe area options not helped.

UITabBar.appearance().isHidden = false and opaque appearance give flickering of whole tabbar. I want to hide default UITabbar to customize my own. Any ideas?

Flickering of bottom safe area: Demonstration GIF

Sample project:

struct ContentView: View {

    @State var selected = "second"

    var body: some View {
        ZStack(alignment: .bottom) {
            VStack(spacing: 0) {
                FirstView()
                TabView(selection: $selected) {
                    SecondView()
                        .tabItem({
                            Text("second")
                        })
                        .tag("second")
                    ThirdView()
                        .tabItem({
                            Text("third")
                        })
                        .tag("third")
                }
            }
            HStack {
                Image(systemName: selected == "second" ? "circle.fill" : "circle")
                    .onTapGesture {
                        selected = "second"
                    }
                Image(systemName: selected == "third" ? "circle.fill" : "circle")
                    .onTapGesture {
                        selected = "third"
                    }
            }
            .frame(width: 70, height: 40, alignment: .center)
            .background(Color.white)
            .cornerRadius(10)
            .padding()
        }
        .edgesIgnoringSafeArea(.all)
        .onAppear {
            UITabBar.appearance().isHidden = true
        }
    }
}
struct FirstView: View {
    
    @State var height:CGFloat = 200
    
    var body: some View {
        ZStack(alignment: .bottom) {
            Color.red
                .frame(height: height)
            Image(systemName: height == 200 ? "arrow.down" : "arrow.up")
                .foregroundColor(.white)
                .padding(5)
                .onTapGesture {
                    withAnimation(.easeInOut(duration: 2)) {
                        height = height == 200 ? 350 : 200
                    }
                }
        }
    }
}
struct SecondView: View {
    var body: some View {
        ZStack {
            Text("hello")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
        .background(Color.green)
        .onAppear {
            UITabBar.appearance().isHidden = true
        }
    }
}
struct ThirdView: View {
    var body: some View {
        Color.blue
            .edgesIgnoringSafeArea(.bottom)
    }
}

Thanks for answers :)



Solution 1:[1]

Since you have your own index navigation anyways, I recommend to get rid of TabView altogether and switch views by if / else or switch statements:

struct ContentView: View {

    @State var selected = "second"

    var body: some View {
        ZStack(alignment: .bottom) {
            VStack(spacing: 0) {
                FirstView()
                if selected == "second" {
                    SecondView()
                } else {
                    ThirdView()
                }
            }
            HStack {
                Image(systemName: selected == "second" ? "circle.fill" : "circle")
                    .onTapGesture {
                        selected = "second"
                    }
                Image(systemName: selected == "third" ? "circle.fill" : "circle")
                    .onTapGesture {
                        selected = "third"
                    }
            }
            .frame(width: 70, height: 40, alignment: .center)
            .background(Color.white)
            .cornerRadius(10)
            .padding()
        }
        .edgesIgnoringSafeArea(.all)
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ChrisR