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!
2
Answers
You can continue to use a
@State
variable forshowText
, which, according to your requirements, should only be shown once theToggle
is interacted with. Rather than using a@State
variable that is initialized with aUserDefaults
value, you probably want to use@AppStorage
forisOn
.Here is a slightly different take on how to solve this. You can have
@AppStorage
store an optional value, so long as you extend optionals toconform to
RawRepresentable
. This allows you to eliminate theshowText
state variable, and allows you a definite state with 3 possibilities, true, false and nil. Since you don’t want the text to show up until theToggle
has been toggled once, the nil state allows you to know this. OnceToggle
has been toggled,isOn
will have either a true or false value from that point forward, unless you set it somewhere else to nil again.There is one complexity that this adds.
Toggle
does not take an Bool?. Therefore, you have to write your own binding for it so that there is a definite value being passed in to theToggle
.