简体   繁体   English

SwiftUI 查看与分段选取器匹配的转换

[英]SwiftUI View Transition matching to an Segmented Picker

Is it possible to have three (more than 2!) views that are animated in and out from the sides according to an Picker with the SegmentedPickerStyle() style?根据具有SegmentedPickerStyle()样式的Picker ,是否可以拥有三个(超过 2 个!)从侧面进出动画的视图?

Having only 2 items in the picker makes the job static and thus a .transition(.move(edge: .leading)) on the first and a .transition(.move(edge: .trailing)) on the last view is sufficient.选择器中只有 2 个项目使得工作 static 和因此第一个视图上的.transition(.move(edge: .leading)) .transition(.move(edge: .trailing))和最后一个视图上的 .transition(.move(edge: .trailing)) 就足够了。 But what about more than 2?但是超过2个呢?

Maybe there is a way to make the edge: ... parameter of the transition dynamically set to .leading or .trailing and depending on whether how the new value of the binding is greater or less than the current on.也许有一种方法可以使edge: ...转换的参数动态设置为.leading.trailing并且取决于绑定的新值是大于还是小于当前值。

I created the following sketch to demonstrate the issue of having the same view (view 2) with a different transition depending on whether a view on its right or left is selected.我创建了下面的草图来演示具有不同转换的相同视图(视图 2)的问题,具体取决于选择其右侧或左侧的视图。 Please see this only as an example, the problem is not restricted to only three segments, nor only the middle view, nor only disappearing transitions etc..请仅将其视为示例,问题不仅限于三个段,也不仅限于中间视图,也不仅限于消失的过渡等。

在此处输入图像描述

Update The secret sauce is to make sure the transition fires with an animation and tell it what direction to go before doing so.更新秘诀是确保使用 animation 触发转换,并在这样做之前告诉它 go 的方向。 Give this a try:试试这个:

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())
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM