I'm trying to transition from the main view to a second view with animation using .matchedGeometryEffect
but for some reason, if I apply the .matchedGeometryEffect
directly to Text(item.name)
only one item is visible, the rest of them get hidden. If I apply the .matchedGeometryEffect
directly to the List
all items show and I get the animation when it moves to the second view but is not the effect I'm looking for, I get a better effect when I apply .matchedGeometryEffect
to Text(item.name)
.
Any idea why most items in the List disappear when I apply .matchedGeometryEffect
to Text(item.name)
?
struct ContentView: View {
@State var showEditView = false
@State var selectedItem:Item?
@Namespace var editViewAnaimation
let items = [Item(name: "Fork", symbolName: "fork.knife"),
Item(name: "Hammer", symbolName: "hammer.fill"),
Item(name: "Lightbulb", symbolName: "lightbulb.fill")]
var body: some View {
VStack {
if showEditView{
Button(action: {
withAnimation{
showEditView.toggle()
}
}, label: {
Image(systemName: "xmark.square.fill")
.foregroundColor(Color.red)
})
EditView( editViewAnaimation: editViewAnaimation, selectedItem: selectedItem!)
}else{
List(items, id:\.self){ item in
HStack{
Image(systemName: item.symbolName)
.foregroundColor(Color.red)
Text(item.name)
.foregroundColor(Color.blue)
/// some items disappear when applied here, why?
//.matchedGeometryEffect(id: "name", in: editViewAnaimation)
}
.onTapGesture {
selectedItem = item
withAnimation{
showEditView.toggle()
}
}
}
/// all items show when applied here but not the effect I want
.matchedGeometryEffect(id: "name", in: editViewAnaimation)
}
}
}
}
struct EditView: View {
var editViewAnaimation: Namespace.ID
let selectedItem:Item
@State var nameInput = ""
var body: some View {
ScrollView{
TextField("name", text: $nameInput)
.textFieldStyle(RoundedBorderTextFieldStyle())
.matchedGeometryEffect(id: "name", in: editViewAnaimation)
}
.padding()
.onAppear{
nameInput = selectedItem.name
}
}
}
You are using the same id for all the Text
s. This means that every Text
's frame would match. The "Fork" text would match "Hammer", and would also match "Lightbulb". All of them would be on top of one another, so you only see one text.
You should put the matchedGeometryEffect
modifier on the Text
s, and give an appropriate id to each of them. For example, you can use the name of the item as the id:
Text(item.name)
.foregroundColor(Color.blue)
.matchedGeometryEffect(id: item.name, in: editViewAnaimation)
TextField("name", text: $nameInput)
.textFieldStyle(RoundedBorderTextFieldStyle())
.matchedGeometryEffect(id: selectedItem.name, in: editViewAnaimation)
You only want the "Fork" Text
to match the "Fork" TextField
, the "Hammer" Text
to match the "Hammer" TextField
etc.