与分段选取器匹配的 SwiftUI 视图转换

问题描述

根据 Picker 样式的 SegmentedPickerStyle() 是否可以有三个(超过 2 个!)视图从侧面进出动画?

选择器中只有 2 个项目会使作业静态化,因此第一个视图上的 .transition(.move(edge: .leading)) 和最后一个视图上的 .transition(.move(edge: .trailing)) 就足够了。但是超过 2 个呢?

也许有一种方法可以让过渡的 edge: ... 参数动态设置为 .leading.trailing 并且取决于绑定的新值是大于还是小于当前打开。

我创建了以下草图来演示具有相同视图(视图 2)和不同过渡的问题,具体取决于选择的是其右侧还是左侧的视图。请看这只是一个例子,问题不仅限于三段,也不限于中间视图,也不限于消失的过渡等。

enter image description here

解决方法

更新 秘诀是确保通过动画触发过渡,并在执行此操作之前告诉它要前进的方向。试试这个:

class TabControllerContext : ObservableObject {
    @Published var selected = panels.one { didSet {
        if previous != selected {
            insertion = selected.makeMove(previous)
            removal = previous.makeMove(selected)

            withAnimation {
                trigger = selected
                previous = selected
            }
        }
    }}
    
    @Published var trigger = panels.one
    @Published var previous = panels.one
    var insertion : AnyTransition = .move(edge: .leading)
    var removal : AnyTransition = .move(edge: .trailing)
}

struct TabsWithTransitionsView: View {
    @EnvironmentObject var context : TabControllerContext
    
    var body: some View {
        VStack {
            Picker("Select Panel",selection: $context.selected) {
                ForEach(panels.allCases) { panel in
                    panel.label.tag(panel)
                }
            }.pickerStyle(SegmentedPickerStyle())
            
            ForEach(panels.allCases) { panel in
                if context.trigger == panel {
                    panel.label
                        .background(panel.color)
                        .transition(.asymmetric(insertion: context.insertion,removal: context.removal))
                }
            }
        }
    }
}

enum panels : Int,CaseIterable,Identifiable {
    case one = 1
    case two = 2
    case three = 3
    
    var label : some View {
        switch self {
        case .one:
            return Label("Tab One",systemImage: "1.circle")
        case .two:
            return Label("Tab Two",systemImage: "2.square")
        case .three:
            return Label("Tab Three",systemImage: "asterisk.circle")
        }
    }
    
    var color : Color {
        switch self {
        case .one: return Color.red.opacity(0.5)
        case .two: return Color.green.opacity(0.5)
        case .three: return Color.blue.opacity(0.5)
        }
    }
    
    func makeMove(_ otherPanel: panels) -> AnyTransition {
        return otherPanel.rawValue < self.rawValue ? .move(edge: .trailing) : .move(edge: .leading)
    }
    
    // so the enum can be indentified when enumerated
    var id : Int { self.rawValue }
}

struct TabsWithTransitionsView_Previews: PreviewProvider {
    static var previews: some View {
        TabsWithTransitionsView().environmentObject(TabControllerContext())
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...