SwiftUI: создание пользовательского сегментированного элемента управления с помощью .matchedGeometry()
В настоящее время я пытаюсь создать какой-то собственный сегментированный элемент управления. Мой код сейчас выглядит так:
@AppStorage("selectedcountry") private var selectedCountry: Country = .france
@Namespace private var animation
HStack {
ForEach(Country.allCases, id: \.self) { country in
Button {
withAnimation {
selectedCountry = country
}
} label: {
Text(country.flag)
.padding()
}
.frame(maxWidth: .infinity)
.background {
if selectedCountry == country {
RoundedRectangle(cornerRadius: 10)
.fill(Color.accentColor)
.matchedGeometryEffect(id: "country", in: animation)
}
}
}
}
Элемент RoundedRectangle(cornerRadius: 10) должен перемещаться, как в обычных сегментированных элементах управления iOS. Но почему-то у меня просто не получается эффект согласованной геометрии.
Какой-нибудь совет, который вы могли бы мне дать?
1 ответ
Вот как заставить это работать:
- Должен быть только один маркер, который можно установить в качестве фона позади
HStack
. - Идентификатор фонового маркера должен совпадать с идентификатором выбранного элемента.
- Необходимо определить источник соответствия геометрическому эффекту. В любой момент времени источником может быть только один элемент.
Так:
HStack {
ForEach(Country.allCases, id: \.self) { country in
Button {
withAnimation {
selectedCountry = country
}
} label: {
Text(country.flag)
.padding()
}
.matchedGeometryEffect(id: country, in: animation, isSource: selectedCountry == country)
.frame(maxWidth: .infinity)
}
}
.background {
RoundedRectangle(cornerRadius: 10)
.fill(Color.accentColor)
.matchedGeometryEffect(id: selectedCountry, in: animation, isSource: false)
}
Я не мог понять, почему маркер прыгал из одной позиции в другую, а не двигался анимированным образом. Но это потому, что обновляемая переменная@AppStorage
вместо . Когда вы измените его на@State
, анимация работает нормально:
@State private var selectedCountry: Country = .france
См. SwiftUI: сохраните состояние переключения и сохраните анимацию для некоторых обходных путей.