SwiftUI - View disappears if animated

杀马特。学长 韩版系。学妹 提交于 2020-12-15 02:03:17

问题


I am building a custom segmented control. This is the code that I have written.

struct SegmentedControl: View {
    private var items: [String] = ["One", "Two", "Three"]
    
    @Namespace var animation:Namespace.ID
    
    @State var selected: String = "One"
    var body: some View {
        ScrollView(.horizontal) {
            HStack {
                ForEach(items, id: \.self) { item in
                    Button(action: {
                        withAnimation(.spring()){
                            self.selected = item
                        }
                    }) {
                        Text(item)
                            .font(Font.subheadline.weight(.medium))
                            .foregroundColor(selected == item ? .white : .accentColor)
                            .padding(.horizontal, 25)
                            .padding(.vertical, 10)
                            .background(zStack(item: item))
                    }
                    
                }
            } .padding()
        }
    }
    
    private func zStack(item: String) -> some View {
        ZStack{
            if selected == item {
                Color.accentColor
                    .clipShape(Capsule())
                    .matchedGeometryEffect(id: "Tab", in: animation)
            } else {
                Color(.gray)
                    .clipShape(Capsule())
            }}
    }
}

A control is Blue when it is selected.

It works as expected most of the time like in the following GIF.

However, sometimes if you navigate back and forth very fast, the Color.accentColor moves off screen and disappears as you see in the following GIF. I have used a lot of time but could not fix it.

Sometimes, I get this error.

 Multiple inserted views in matched geometry group Pair<String, 
    ID>(first: "Tab", second: SwiftUI.Namespace.ID(id: 248)) have `isSource: 
    true`, results are undefined.

Info, It is easier to test it on a physical device rather than a simulator.

Update

This is my all codde including the ContentView and the Modal.

struct ContentView: View {
    
    @State private  var isPresented: Bool = false
    
    var body: some View {
        NavigationView {
            VStack {
                Button(action: {
                    self.isPresented.toggle()
                }, label: {
                    Text("Button")
                })
            }
        }
        .sheet(isPresented: $isPresented, content: {
            ModalView()
        })
    }
}

struct ModalView: View {
    var body: some View {
        NavigationView {
            NavigationLink(
                destination: TabbarView(),
                label: {
                   Text("Navigate")
                })
        }
    }
}


struct TabbarView: View {
    private var items: [String] = ["One", "Two", "Three"]
    
    @Namespace var animation:Namespace.ID
    
    @State var selected: String = ""    // change here
    var body: some View {
        ScrollView(.horizontal) {
            HStack {
                ForEach(items, id: \.self) { item in
                    Button(action: {
                        withAnimation{
                            self.selected = item
                        }
                    }) {
                        Text(item)
                            .font(Font.subheadline.weight(.medium))
                            .foregroundColor(selected == item ? .white : .accentColor)
                            .padding(.horizontal, 25)
                            .padding(.vertical, 10)
                            .background(zStack(item: item))
                    }
                    
                }
            } .padding()
        }
        .onAppear { self.selected = "One" }  // add this
    }
    
    private func zStack(item: String) -> some View {
        ZStack{
            if selected == item {
                Color.accentColor
                    .clipShape(Capsule())
                    .matchedGeometryEffect(id: "Tab", in: animation)
            } else {
                Color(.gray)
                    .clipShape(Capsule())
            }}
    }
}

来源:https://stackoverflow.com/questions/65131895/swiftui-view-disappears-if-animated

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!