【发布时间】:2021-03-10 11:02:51
【问题描述】:
我正在 SwiftUI 中构建一个自定义 SegmentedPicker,其中选择器会调整其大小以适应每个选择器项目的框架。我已经在这篇文章 (Inspecting the View Tree) 的启发下使用 PreferenceKeys 来处理统一大小的项目,如下所示:
我认为我可以通过使用.matchedGeometryEffect() 来大大简化我的实现并完全避免使用PreferencyKeys。我的想法是仅在选择该项目时在每个项目后面显示一个选择器,并使用 .matchedGeometryEffect() 同步过渡。除了选择器将位于先前选择的项目前面的问题之外,几乎一切都在工作。我尝试显式设置zIndex,但似乎不影响结果:
代码:
struct MatchedGeometryPicker: View {
@Namespace private var animation
@Binding var selection: Int
let items: [String]
var body: some View {
HStack {
ForEach(items.indices) { index in
ZStack {
if isSelected(index) {
Color.gray.clipShape(Capsule())
.matchedGeometryEffect(id: "selector", in: animation)
.animation(.easeInOut)
.zIndex(0)
}
itemView(for: index)
.padding(7)
.zIndex(1)
}
.fixedSize()
}
}
.padding(7)
}
func itemView(for index: Int) -> some View {
Text(items[index])
.frame(minWidth: 0, maxWidth: .infinity)
.foregroundColor(isSelected(index) ? .black : .gray)
.font(.caption)
.onTapGesture { selection = index }
}
func isSelected(_ index: Int) -> Bool { selection == index }
}
在ContentView:
struct ContentView: View {
@State private var selection = 0
let pickerItems = [ "Item 1", "Long item 2", "Item 3", "Item 4", "Long item 5"]
var body: some View {
MatchedGeometryPicker(selection: $selection, items: pickerItems)
.background(Color.gray.opacity(0.10).clipShape(Capsule()))
.padding(.horizontal, 5)
}
}
任何想法如何解决这个问题?
【问题讨论】:
-
为什么使用 PreferenceKeys 的工作代码不适合使用和尝试这种方式?
-
@swiftPunk with PreferenceKeys 如果每个项目都具有相同的框架,它会很好地工作,但我仍在尝试解决选择器尺寸的动画问题。使用
.matchedGeometryEffect(),选择器可以完美地动画位置和尺寸变化,并且代码更简单。我只需要弄清楚如何解决分层问题...
标签: swiftui z-index picker segmentedcontrol swiftui-geometryeffect