繁体   English   中英

(SwiftUI)如何在视图加载时隐藏文本并在点击切换后变得可见

[英](SwiftUI) How to make text hidden when view loads and become visible once toggle is tapped

我正在尝试创建一个带有toggle的视图。 切换更改 ui 首选项。 更改切换时,它会更改下面的Text 因为它代表最简单的方法是

        VStack {
            Toggle("toggle me", isOn: $isOn)
            Text( isOn ? "I've been toggled once more" : "I've been toggled again" )
         }

我想要的是Text( isOn? "I've been toggled once more": "I've been toggled again" )直到与切换交互之后 打开或关闭它都没有关系,我想在与切换进行交互后使文本可见。 我试过使用.onChange(of: perform: )perform:需要一个 void 方法。 所以我不能把文本放在那里。 我已尝试使用布尔值/不透明度修复,如此处的答案所示,但问题相同。 无法更改执行中的 Boolean 值。 只允许 void 方法。 我确实尝试使用onTapGesture但那根本不起作用。 我在那里有一份打印声明,从未打印过。 不知道还能做什么。 是否可以在与切换进行交互之前隐藏文本? 这是我的代码

struct ProfileView: View {
    
    @State private var isOn = UserDefaults.standard.bool(forKey: "isOn")
    @State private var showText = false
    
    var body: some View {
        VStack { // vstack 0
            Text("Profile Page")
                .font(.title)
            
            Text("Are you ready to toggle?")
                .font(.title2)
                .multilineTextAlignment(.center)
            
            VStack { // vstack 1
                Toggle("toggle this", isOn: $isOn)
                    .onTapGesture {
                        print("toggled") // this never prints
                    }
//                    .onChange(of: isOn, perform: { value in
//                        value ? Text("yes") : Text("no")
//                        print("value = \(value)")
//                    })
// the Text here never shows up. and can't set showText = true here
                Text( isOn ? "Thank you." : "Toggled again" )
                    .opacity(showText ? 1 : 0)
// from the linked stackoverflow answer. trying to make this boolean work. is it a lost cause? 
            } // vstack 1
        } // vstack 0
        .frame(
            width: UIScreen.main.bounds.width,
            height: UIScreen.main.bounds.height - 200,
            alignment: .top)
    }
}

那我问的是可能的吗? 谢谢您的帮助!

您可以继续为showText使用@State变量,根据您的要求,只有在与Toggle交互后才应显示该变量。 您可能不希望使用使用UserDefaults值初始化的@State变量,而是将@AppStorage用于isOn

struct ProfileView: View {
    
    @AppStorage("isOn") private var isOn : Bool = false //@AppStorage syncs this value with UserDefaults automatically
    @State private var showText = false
    
    var body: some View {
        VStack { // vstack 0
            Text("Profile Page")
                .font(.title)
            
            Text("Are you ready to toggle?")
                .font(.title2)
                .multilineTextAlignment(.center)
            
            VStack { // vstack 1
                Toggle("toggle this", isOn: $isOn)
                    .onChange(of: isOn, perform: { value in
                        showText = true //Once the toggle is interacted with, set showText to true
                    })
                if showText { //only show the text if showText == true
                    Text( isOn ? "Thank you." : "Toggled again" )
                }
            } // vstack 1
        } // vstack 0
        .padding(.bottom, 200) //try not to use UIScreen dimensions in SwiftUI -- default to using padding instead when possible
    }
}

关于如何解决这个问题,这里有一个稍微不同的看法。 您可以让@AppStorage存储可选值,只要您扩展可选值以符合RawRepresentable 这允许您消除showText state 变量,并允许您使用 3 种可能性确定 state,true、false 和 nil。 由于您不希望在Toggle一次切换之前显示文本,因此 nil state 让您知道这一点。 一旦Toggle被切换, isOn将有一个 true 或 false 值,除非你在其他地方再次将它设置为 nil。

这增加了一种复杂性。 Toggle不需要 Bool?。 因此,您必须为其编写自己的绑定,以便将确定的值传递给Toggle

struct ProfileView: View {
    
    @AppStorage("isOn") private(set) var isOn: Bool? = nil

    var body: some View {
        VStack { // vstack 0
            Text("Profile Page")
                .font(.title)
            
            Text("Are you ready to toggle?")
                .font(.title2)
                .multilineTextAlignment(.center)
            
            VStack { // vstack 1
                Toggle("toggle this", isOn: Binding<Bool>(
                    get: { isOn ?? false },
                    set: { isOn = $0 }
                ))
                    .onTapGesture {
                        print("toggled") // this never prints
                    }
                Text( isOn == true ? "Thank you." : "Toggled again" )
                    // Compare isOn to nil, instead of use showText
                    .opacity(isOn != nil ? 1 : 0)
            } // vstack 1
            Spacer()
        } // vstack 0
        .padding()
    }
}

// This extension allows Optionals to be written to @AppStorage
extension Optional: RawRepresentable where Wrapped: Codable {
    public var rawValue: String {
        guard let data = try? JSONEncoder().encode(self),
              let json = String(data: data, encoding: .utf8)
        else {
            return "{}"
        }
        return json
    }

    public init?(rawValue: String) {
        guard let data = rawValue.data(using: .utf8),
              let value = try? JSONDecoder().decode(Self.self, from: data)
        else {
            return nil
        }
        self = value
    }
}

暂无
暂无

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

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