【问题标题】:How to animate a rectangle traveling between buttons headings?如何为在按钮标题之间移动的矩形设置动画?
【发布时间】:2021-10-06 22:14:31
【问题描述】:

我有一组按钮,其行为类似于分段选择器。当你点击一个按钮时,它会更新一个枚举状态。我想在顶部显示一个在按钮之间运行的指示器,而不是显示/隐藏。

这就是我所拥有的:

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 会帮助做到这一点,但我可能使用错误或存在更好的方法。如果按钮顶部的黑线在一个按钮上进行动画处理并在另一个按钮上移动,我该如何实现这一点?

【问题讨论】:

    标签: animation swiftui


    【解决方案1】:

    你错过了动画:

     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"
            }
        }
    }
    

    【讨论】:

    • 哇,它成功了!谢谢!!
    • 不客气! ?
    • @TruMan1:我看到您的代码需要进行一些必要的重构,如果您有兴趣,我可以更新我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    • 1970-01-01
    • 2014-07-12
    • 1970-01-01
    • 2019-07-11
    • 1970-01-01
    相关资源
    最近更新 更多