简体   繁体   English

SwiftUI TabView 在 Orientation Change 上工作不正常

[英]SwiftUI TabView is not working properly on Orientation Change

I created a simple tabView like this我像这样创建了一个简单的tabView

struct ContentView: View {
    var body: some View {
        TabView{
            TabItemView(color: .red, title: "Page 1")
            TabItemView(color: .yellow, title: "Page 2")
            TabItemView(color: .green, title: "Page 3")
            TabItemView(color: .blue, title: "Page 4")
        }
        .tabViewStyle(.page)
        .background(Color.indigo)
    }
}

where在哪里

struct TabItemView: View {
    var color : Color
    var title : String
    var body: some View {
        Text("\(title)")
            .frame(width:UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
            .background(color)
        
    }
}

issue is when is switch to landscape entire thing is broken, like this问题是什么时候切换到横向整个东西都坏了,就像这样景观视图

ie the tabs are jumped back to either some random position or position between two.即选项卡跳回到两个之间的某个随机 position 或 position。

I searched online and some resources say its a bug thats not solved yet.我在网上搜索,一些资源说它是一个尚未解决的错误。 Any solution for this?有什么解决办法吗?

Hi the bug is well known.嗨,这个错误是众所周知的。 Generally it helps when you put the tabview into inactive scrollview with certain frame modifier, like this:通常,当您使用某些框架修饰符将 tabview 放入非活动滚动视图时,它会有所帮助,如下所示:

struct ContentView: View {
    var body: some View {
        ScrollView([])
            TabView{
                TabItemView(color: .red, title: "Page 1")
                TabItemView(color: .yellow, title: "Page 2")
                TabItemView(color: .green, title: "Page 3")
                TabItemView(color: .blue, title: "Page 4")
            }
            .tabViewStyle(.page)
            .background(Color.indigo)
        }
    }
    .frame(width: UIScreen.main.bounds.width)
}

This should fix the views in the middle in case of rotations.这应该在旋转的情况下将视图固定在中间。 However, it might happen that when you use some array and iterate over it using ForEach inside the TabView, the elements are arbitrarily changed by TabView while rotating view.但是,当您使用某个数组并使用 TabView 内的 ForEach 对其进行迭代时,可能会发生这样的情况,即旋转视图时 TabView 会任意更改元素。 In that case it helps to keep tracking the current and previous orientation using states and build some logic onChange to prevent TabView to doing that.在这种情况下,它有助于使用状态跟踪当前和先前的方向,并在 onChange 上构建一些逻辑以防止 TabView 这样做。 Like some wrapper adding layer between the binded state. Like:就像一些包装器在绑定的 state 之间添加层一样。像:

struct TabView: View {
    @State var pages: Int = 1
    var array: [Int] = [1,2,3,4,5]

    var body: some View {
        VStack {
            TabViewContent(selection: $pages, usage: .one) {
                ForEach(array, id: \.self) { index in
                    Text("This is: \(pages) \(index)")
                    .tag(index)
                }
            }
        }
    }
}

Wrapper with logic:具有逻辑的包装器:

struct TabViewContent<Selection: Hashable, Content: View>: View {
    @Binding var selection: Selection
    @State var selectionInternal: Selection

    @State var previousOrientation: UIDeviceOrientation = .unknown
    @State var currentOrientation: UIDeviceOrientation = .unknown

    @ViewBuilder var content: () -> Content

    internal init(selection: Binding<Selection>,     content: @escaping () -> Content) {
        self.content = content
        _selection = selection
        _selectionInternal = State(initialValue: selection.wrappedValue)
    }

    var body: some View {
        TabView(selection: $selection, content: content)
            .tabViewStyle(.page)
            .onChange(of: UIDevice.current.orientation) { newOrientation in
                currentOrientation = newOrientation
            }
            .onChange(of: selectionInternal) { value in
                if currentOrientation == previousOrientation {
                    selection = selectionInternal
                }

                previousOrientation = currentOrientation
            }
    }
}

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

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