如何为在按钮标题之间移动的矩形设置动画?
How to animate a rectangle traveling between buttons headings?
我有一组按钮,它们的行为类似于分段选择器。当您点击一个按钮时,它会更新状态中的枚举。我想在顶部显示一个在按钮之间运行的指示器,而不是 show/hide。
这是我的:
struct ContentView: View {
enum PageItem: String, CaseIterable, Identifiable {
case page1
case page2
var id: String { rawValue }
var title: LocalizedStringKey {
switch self {
case .page1:
return "Page 1"
case .page2:
return "Page 2"
}
}
}
@Namespace private var pagePickerAnimation
@State private var selectedPage: PageItem = .page1
var body: some View {
HStack(spacing: 16) {
ForEach(PageItem.allCases) { page in
Button {
selectedPage = page
} label: {
VStack {
if page == selectedPage {
Rectangle()
.fill(Color(.label))
.frame(maxWidth: .infinity)
.frame(height: 1)
.matchedGeometryEffect(id: "pageIndicator", in: pagePickerAnimation)
}
Text(page.title)
.padding(.vertical, 8)
.padding(.horizontal, 12)
}
.contentShape(Rectangle())
}
}
}
.padding()
}
}
我认为 matchedGeometryEffect
可以帮助做到这一点,但我可能用错了它或者存在更好的方法。如果按钮顶部的黑线在一个按钮上动画并在另一个按钮上移动,我该如何实现这一点?
您错过了动画:
struct ContentView: View {
@Namespace private var pagePickerAnimation
@State private var selectedPage: PageItem = .page1
var body: some View {
HStack(spacing: 16) {
ForEach(PageItem.allCases) { page in
Button { selectedPage = page } label: {
VStack {
if page == selectedPage {
Rectangle()
.fill(Color(.label))
.frame(maxWidth: .infinity)
.frame(height: 1)
.matchedGeometryEffect(id: "pageIndicator", in: pagePickerAnimation)
}
Text(page.title)
.padding(.vertical, 8)
.padding(.horizontal, 12)
}
.contentShape(Rectangle())
}
}
}
.padding()
.animation(.default, value: selectedPage) // <<: here
}
}
enum PageItem: String, CaseIterable, Identifiable {
case page1
case page2
var id: String { rawValue }
var title: LocalizedStringKey {
switch self {
case .page1:
return "Page 1"
case .page2:
return "Page 2"
}
}
}
我有一组按钮,它们的行为类似于分段选择器。当您点击一个按钮时,它会更新状态中的枚举。我想在顶部显示一个在按钮之间运行的指示器,而不是 show/hide。
这是我的:
struct ContentView: View {
enum PageItem: String, CaseIterable, Identifiable {
case page1
case page2
var id: String { rawValue }
var title: LocalizedStringKey {
switch self {
case .page1:
return "Page 1"
case .page2:
return "Page 2"
}
}
}
@Namespace private var pagePickerAnimation
@State private var selectedPage: PageItem = .page1
var body: some View {
HStack(spacing: 16) {
ForEach(PageItem.allCases) { page in
Button {
selectedPage = page
} label: {
VStack {
if page == selectedPage {
Rectangle()
.fill(Color(.label))
.frame(maxWidth: .infinity)
.frame(height: 1)
.matchedGeometryEffect(id: "pageIndicator", in: pagePickerAnimation)
}
Text(page.title)
.padding(.vertical, 8)
.padding(.horizontal, 12)
}
.contentShape(Rectangle())
}
}
}
.padding()
}
}
我认为 matchedGeometryEffect
可以帮助做到这一点,但我可能用错了它或者存在更好的方法。如果按钮顶部的黑线在一个按钮上动画并在另一个按钮上移动,我该如何实现这一点?
您错过了动画:
struct ContentView: View {
@Namespace private var pagePickerAnimation
@State private var selectedPage: PageItem = .page1
var body: some View {
HStack(spacing: 16) {
ForEach(PageItem.allCases) { page in
Button { selectedPage = page } label: {
VStack {
if page == selectedPage {
Rectangle()
.fill(Color(.label))
.frame(maxWidth: .infinity)
.frame(height: 1)
.matchedGeometryEffect(id: "pageIndicator", in: pagePickerAnimation)
}
Text(page.title)
.padding(.vertical, 8)
.padding(.horizontal, 12)
}
.contentShape(Rectangle())
}
}
}
.padding()
.animation(.default, value: selectedPage) // <<: here
}
}
enum PageItem: String, CaseIterable, Identifiable {
case page1
case page2
var id: String { rawValue }
var title: LocalizedStringKey {
switch self {
case .page1:
return "Page 1"
case .page2:
return "Page 2"
}
}
}