SwiftUI如何实现分段选择器按钮间的指示条平滑移动动画
解决方案
核心问题在于原实现缺少两个关键配置:
- 没有为状态变更添加动画触发上下文,
matchedGeometryEffect的转场动画需要在动画块内修改状态才会生效 - 非选中状态的按钮顶部没有和指示条等高的占位元素,会导致选中时按钮高度突变,打断平滑过渡效果
修改后的完整实现代码如下:
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 { // 包裹动画块触发过渡效果 withAnimation(.easeInOut(duration: 0.2)) { selectedPage = page } } label: { VStack(spacing: 0) { // 固定间距避免垂直偏移 // 所有按钮统一保留1px高度的条,选中态为实色,非选中态为透明占位 Group { if page == selectedPage { Rectangle() .fill(Color(.label)) .matchedGeometryEffect(id: "pageIndicator", in: pagePickerAnimation) } else { Rectangle() .fill(.clear) } } .frame(maxWidth: .infinity) .frame(height: 1) Text(page.title) .padding(.vertical, 8) .padding(.horizontal, 12) } .contentShape(Rectangle()) } } } .padding() } }
该方案可直接扩展到更多按钮的场景,只需给PageItem枚举新增对应case即可,无需修改其他逻辑。
内容的提问来源于stack exchange,提问作者TruMan1
相关产品推荐
相关产品推荐

