SwiftUI 共享不同方向的子视图状态

问题描述 投票:0回答:1

我有一个 SwiftUI 视图,它针对不同的界面方向具有不同的布局。我使用类似的东西来实现它(只是为了最小化可重现的示例代码,我在下面包含了一个示例代码)。

import SwiftUI

struct ContentView: View {

 @Environment(\.dismiss) private var dismiss
 @Environment(\.verticalSizeClass) private var verticalSizeClass
 @Environment(\.horizontalSizeClass) private var horizontalSizeClass

 var body: some View {
     ZStack(content: {
         if verticalSizeClass == .regular {
             testView
         } else {
             testView
         }
     })
 }

 var testView: some View {
    TestView()
 }

}

 struct TestView: View {
    @State var isSelected = false

   var body: some View {
     VStack {
         Image(systemName: "globe")
             .imageScale(.large)
             .foregroundStyle(.tint)
         Text("Hello, world!")
      }
     .padding()
     .overlay {
        if isSelected {
            RoundedRectangle(cornerRadius: 5)
                .stroke(.yellow, lineWidth: 3.0)
        }
     }
    .gesture(
        TapGesture(count: 1)
            .onEnded({ _ in
                isSelected.toggle()
            })
    )
   }
 }

在自动旋转时,SwiftUI 会将

TestView
视为具有不同身份的单独视图,因此该视图将丢失其当前状态(上例中的
isSelected
)并将被重新绘制为新的视图。

解决此类问题的正确方法是什么?是否可以为各个子视图分配身份,以便它们保留自动旋转的状态?因为在原来的项目中,两个方向都有很多共同的子视图。

ios swift swiftui
1个回答
0
投票

在 testView 内部移动不同方向的尺寸类环境值和逻辑,因此 testView 在方向变化时将具有相同的标识,并且方向更新仅发生在 testView 内部。

struct ContentView: View {

    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        ZStack(content: {
            testView
        })
    }
    
    var testView: some View {
        TestView()
    }
}

struct TestView: View {
    @State var isSelected = false
    @Environment(\.verticalSizeClass) private var verticalSizeClass
    @Environment(\.horizontalSizeClass) private var horizontalSizeClass
    
    var body: some View {
        VStack {
            if verticalSizeClass == .regular {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundStyle(.tint)
                Text("Hello, world!")
            } else {
                HStack {
                    Image(systemName: "globe")
                        .imageScale(.large)
                        .foregroundStyle(.tint)
                    Text("Hello, world!")
                }
                .transition(.scale)
            }
        }
        .padding()
        .overlay {
            if isSelected {
                RoundedRectangle(cornerRadius: 5)
                    .stroke(.yellow, lineWidth: 3.0)
            }
        }
        .gesture(
            TapGesture(count: 1)
                .onEnded({ _ in
                    isSelected.toggle()
                })
        )
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.