SwiftUI: Setting View visibility based on a property value?

Viewed 11592

When defining a view hierarchy using SwiftUI, is it possible to set the hidden() value of a View in the body of the definition?

For example:

var body: some View {
     VStack(alignment: .leading) {
          Text(self.name)
          .font(.headline)
          .hidden()
     }
}

would hide the Text object, but I would like to use a boolean property to toggle visibility.

There is a way to do this using a ternary operator and the opacity value of the view, but I was hoping for a less clever solution.

Thanks!

2 Answers

If you don't want to use the opacity modifier this way:

struct ContentView: View {
    @State private var showText = true

    var body: some View {
         VStack(alignment: .leading) {
              Text("Hello world")
                .font(.headline)
                .opacity(showText ? 1 : 0)
         }
    }
}

you can decide to completely remove the view conditionally:

struct ContentView: View {
    @State private var showText = true

    var body: some View {
         VStack(alignment: .leading) {
            if showText {
                Text("Hello world")
                    .font(.headline)
            }
         }
    }
}

Consider that both ways are widely used in SwiftUI. For your specific case I'd honestly use the opacity modifier, but even the removal is fine.

Don't know if its still use useful because it's been a long time and I guess you found a solution since.But for anyone who's interested, we could create a modifier, which switches the visibility of the view according to a binding value :

import SwiftUI

struct IsVisibleModifier : ViewModifier{
    
    @Binding var isVisible : Bool
    // the transition will add a custom animation while displaying the 
    // view.
    var transition : AnyTransition

    func body(content: Content) -> some View {
        ZStack{
            if isVisible{
                content
                    .transition(transition)
            }
        }
    }
}

extension View {

    func isVisible(
        isVisible : Binding<Bool>,
        transition : AnyTransition = .scale
    ) -> some View{
        modifier(
            IsVisibleModifier(
                isVisible: isVisible,
                transition: transition
            )
        )
    }
}

In use :

        Text("Visible")
            .isVisible(isVisible: $isVisible)
            .animation(.easeOut(duration: 0.3), value: isVisible)
Related