![](/img/trans.png)
[英]How can I make a collectionView header become hidden when a button is tapped?
[英](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.