I'm trying to create a view with a toggle
. the toggle changes ui preferences. when the toggle is changed it changes the Text
below. as it stands the easiest way to do this is
VStack {
Toggle("toggle me", isOn: $isOn)
Text( isOn ? "I've been toggled once more" : "I've been toggled again" )
}
what I would like is for the Text( isOn ? "I've been toggled once more" : "I've been toggled again" )
to be hidden until after the toggle is interacted with. it doesn't matter if it's been toggled on or off, I would like to make the Text visible once the toggle has been interacted with. I've tried to use the .onChange(of: perform: )
but perform:
requires a void method. so I can't put the Text in there. I have tried using a boolean/opacity fix as shown in the answer here but same problem. can't change a Boolean value in perform. only void methods are allowed. I did try to use onTapGesture
but that didn't work at all. I had a print statement in there that never once printed. not sure what else to do. is it possible to keep text hidden until the toggle has been interacted with? here's my code
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)
}
}
So is what I'm asking even possible? Thanks for the help!
You can continue to use a @State
variable for showText
, which, according to your requirements, should only be shown once the Toggle
is interacted with. Rather than using a @State
variable that is initialized with a UserDefaults
value, you probably want to use @AppStorage
for 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
}
}