Dynamically hiding view in SwiftUI
The simplest and most common way to hide a view is like the following:
struct ContentView: View {
@State private var showText = true
var body: some View {
VStack {
Button("Toggle text") {
showText.toggle()
}
if showText {
Text("Hello World!")
}
}
}
}
This removes the Text
view from the hierarchy when showText
equals false
. If you wish to have an option to preserve the space or want it as a modifier, see below.
I created an extension, so you can use a modifier, like so to hide the view:
Text("Hello World!")
.isHidden(true)
Or for complete removal:
Text("Label")
.isHidden(true, remove: true)
The extension below is also available on GitHub here if you want to use Swift Packages: GeorgeElsham/HidingViews.
Here is the code to create the View
modifier:
I recommend you use this code in its own file (remember to import SwiftUI
):
extension View {
/// Hide or show the view based on a boolean value.
///
/// Example for visibility:
///
/// Text("Label")
/// .isHidden(true)
///
/// Example for complete removal:
///
/// Text("Label")
/// .isHidden(true, remove: true)
///
/// - Parameters:
/// - hidden: Set to `false` to show the view. Set to `true` to hide the view.
/// - remove: Boolean value indicating whether or not to remove the view.
@ViewBuilder func isHidden(_ hidden: Bool, remove: Bool = false) -> some View {
if hidden {
if !remove {
self.hidden()
}
} else {
self
}
}
}
✅ The correct and Simplest Way:
You can set the alpha instead, this will preserve the layout space of the view too and does not force you to add dummy views like the other answers:
.opacity(isHidden ? 0 : 1)
Demo
ð¡ Cleaner Way! - Extend original hidden
modifier:
Also, you can implement a custom function to get the visibility state as an argument:
extension View {
func hidden(_ shouldHide: Bool) -> some View {
opacity(shouldHide ? 0 : 1)
}
}
Now just pass the bool
to the modifier:
DatePicker($datePickerDate)
.hidden(showDatePicker)
Note that unlike the original behavior of the hidden
modifier, both of these methods preserve the frame of the hiding view.
⛔️ Don't use bad practices !!!
All other answers (including the accepted answer by @Jake) use branches instead of dependent code that cause a performance hit.
ð Branch example:
✅ Dependent Code example:
Returning logical SAME view for different states causes the SwiftUI to render engine to re-render and initial a view again and cause a performance hit! (see more at this WWDC session)