我正在使用SwiftUI的PageTabViewStyle()
tabView风格实现一个滑动标签视图,类似于Reddit mobile。顶部是所有变为蓝色的选项卡名称,右下方是移动到所选选项卡的小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语句中,等等),但是没有成功,我在标签之间滑动,或者点击其中一个标签名称,胶囊就跳到那个标签。
发布于 2021-02-01 23:24:22
您需要将.matchedGeometryEffect放在胶囊上,但只有在选中选项卡时才绘制胶囊(使用if-语句)。您还需要向胶囊中添加动画。下面是一个示例:
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())
}
}
}
}
}
}
https://stackoverflow.com/questions/66001383
复制相似问题