首页 > 解决方案 > 在选项卡视图之一中切换 TabView 中的选项卡“重置”matchedGeometryEffect()

问题描述

我有一个三选项卡视图,在第一个选项卡中另一个选项卡视图,这次设置为PageTabViewStyle(). 在这个可滑动的选项卡视图中TabHeader,它包含所有选项卡名称或“类别”,在一个 中HStack,以及选项卡名称下的一个胶囊,它根据所选选项卡使用matchedGeometryEffect()- 移动,它就像一个魅力。这是我的一些代码:

// The parent view
@StateObject private var tabModel = TabBarViewModel()
// [...]
TabView(selection: $tabModel.selectedTab) {
    History()
        .tag(Tab.history) // the tab is actually hidden since I'm using a custom tab bar, which is why there aren't any `tabItem`
    Text("Tap view")
        .tag(Tab.tap)
    Text("Profile view")
        .tag(Tab.profile)
}

历史视图为:

@State private var currentCategory: Category

init() {
    _currentCategory = State(initialValue: categories[0]) // user makes their own categories, so can't use enum
}
// [...]
VStack(spacing: 0) {
    NavigationBar(title: Text("History")) { // Custom navigation bar
        TabHeader(categories, selection: $currentCategory, name: \.name)
    }
    TabView(selection: $currentCategory) {
        ForEach(categories, id: \.self) { category in
            HistoryList(category: category)
                .tag(category)
        }
    }
    .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
}

TabHeader 为:

@Binding var currentTab: Category
@Namespace private var animation
// [...]
ScrollView(.horizontal, showsIndicators: false) {
    HStack(spacing: 20) {
        ForEach(tabs, id: \.self) { tab in
            VStack(alignment: .leading, spacing: 5) {
                Button {
                    withAnimation {
                        currentTab = tab
                    }
                } label: {
                    Text(tabNames[tab] ?? "")
                        .foregroundColor(currentTab == tab ? .blue : .gray)
                }
                TabCapsule(for: tab, current: currentTab, animation: animation)
            }
        }
    }
}
.animation(.linear(duration: 0.1))

最后,TabCapsule:

let tab: Category
let currentTab: Category
let animation: Namespace.ID
// [...]
if currentTab == tab {
    Capsule()
        .frame(width: 20, height: 2)
        .foregroundColor(.blue)
        .matchedGeometryEffect(id: "Capsule", in: animation, properties: .position)
} else {
    Capsule()
        .frame(width: 20, height: 2)
        .hidden()
}

历史选项卡视图及其matchedGeometryEffect()胶囊完美运行。但是,当合并到父选项卡视图中时,它的效果不太好。实际上,当我从另一个选项卡(例如,“点击”或“配置文件”选项卡(如父视图中所示))切换到“历史记录”选项卡时,然后从右向左滑动一次以转到另一个类别,胶囊的运动只是一次波涛汹涌,几乎不存在 - 只是通常的淡入淡出。但是,当我再次滑动到另一个类别,或者回到上一个类别时,移动是平滑和正常的,并且保持平滑。似乎回到历史选项卡“重置”了matchedGeometryEffect().

我认为可能是 SwiftUI 在切换到另一个选项卡时破坏了历史视图。但是不,类别甚至位置ScrollView保持不变。我也尝试将currentCategorystate 变量移到它自己的变量中ObservableObject并使用 a StateObject,但它没有任何区别。

您认为是什么导致了这种行为?

标签: iosswiftswiftui

解决方案


推荐阅读