【问题标题】:Make Capsule() move when swiping between tabs - matchedGeometryEffect在标签之间滑动时使 Capsule() 移动-matchedGeometryEffect
【发布时间】:2021-02-02 07:24:22
【问题描述】:

我正在使用 SwiftUI 的 PageTabViewStyle() tabView 样式实现滑动标签视图,类似于 Reddit 移动版。顶部是所有变成蓝色的选项卡名称,在一个小的Capsule() 下方,它移动到选定的选项卡。但是,当用户转到新标签时,我很难使用 matchedGeometryEffect() 移动胶囊。

// The parent view
@State private var selectedTab: Category = .all
// [...]
VStack(spacing: 0) {
    HistoryNavigationBar(selectedTab: $selectedTab)
    TabView(selection: $selectedTab) {
        ForEach(Category.allCases, id: \.self) { category in
            HistoryList(category: category)
        }
    }
    .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
}

HistoryNavigationBar 的重要部分是:

@Namespace private var animation
// [...]
ForEach(History.Category.allCases, id: \.self) { category in
    VStack(alignment: .leading, spacing: 5) {
        Button(action: { selectedTab = category }) {
            Text(category.rawValue.capitalized)
                .foregroundColor(selectedTab == category ? .blue : .gray)
        }
        Capsule()
            .frame(width: 20, height: 2)
            .foregroundColor(selectedTab == category ? .blue : .clear)
    }
}

我应该如何实现matchedGeometryEffect() 以获得每次标签更改时胶囊移动的预期效果?我尝试了与matchedGeometryEffect() 的各种组合(将其放在胶囊之后,将胶囊放在 if 语句中等),但没有成功 - 每当我在选项卡之间滑动或单击其中一个选项卡名称时,胶囊只是跳到那个标签。

【问题讨论】:

    标签: ios swift swiftui


    【解决方案1】:

    您需要将 .matchedGeometryEffect 放在胶囊上,但仅在选择选项卡时绘制胶囊(使用 if 语句)。您还需要为 Capsule 添加动画。这是一个例子:

    struct MGE: View {
        
        @State var selectedTab: String = "one"
        @Namespace private var namespace
    
        enum Category: String, CaseIterable {
            case one, two, three
        }
        
        var body: some View {
            HStack(alignment: .top) {
                ForEach(Category.allCases, id: \.self) { category in
                    VStack(alignment: .leading, spacing: 5) {
                        Button(action: { selectedTab = category.rawValue }) {
                            Text(category.rawValue.capitalized)
                                .foregroundColor(selectedTab == category.rawValue ? .blue : .gray)
                        }
                        if selectedTab == category.rawValue {
                            Capsule()
                                .frame(width: 20, height: 2)
                                .foregroundColor(.blue)
                                .matchedGeometryEffect(id: "capsule", in: namespace)
                                .animation(.spring())
                        }
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 谢谢,效果很好!我在 if 语句后面的else 块中添加了同帧的hidden() 胶囊,这样文本就不会上下跳动。但是,我遇到了另一个问题——如果我在选项卡之间快速跳转,或者快速点击不同的选项卡按钮来切换选项卡,两种情况中的任何一种都会发生,看似随机:要么胶囊的运动变得零星,进入错误的标签名称或在选项卡名称之间跳转,或者应用程序崩溃。我猜这与matchedGeometryEffect() 有关,它阻塞了主线程。你有什么建议?
    • 乐于助人。仅供参考,在我的代码中 ^^ 我使 HStack 具有 .top 对齐,以避免文本跳下。 ...我无法在预览中复制应用程序崩溃,所以我不确定是什么原因造成的。您可以尝试的一件事是在matchedGeometryEffect 上设置isSource。
    猜你喜欢
    • 1970-01-01
    • 2015-04-14
    • 1970-01-01
    • 2017-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多