web-dev-qa-db-fra.com

Masquage dynamique de la vue dans SwiftUI

J'essaie de masquer conditionnellement un DatePicker dans SwiftUI. Cependant, je rencontre des problèmes avec les types incompatibles:

var datePicker = DatePicker($datePickerDate)
if self.showDatePicker {
    datePicker = datePicker.hidden()
}

Dans ce cas, datePicker est un type DatePicker<EmptyView> Mais datePicker.hidden() est un _ModifiedContent<DatePicker<EmptyView>, _HiddenModifier>. Je ne peux donc pas affecter datePicker.hidden() à datePicker. J'ai essayé des variantes de cela et je n'arrive pas à trouver un moyen qui fonctionne. Des idées?

MISE À JOUR

Vous pouvez déballer le type _ModifiedContent Pour obtenir le type sous-jacent à l'aide de sa propriété content. Cependant, cela ne résout pas le problème sous-jacent. La propriété content semble être simplement le sélecteur de date d'origine et non modifié.

22
Jake

Plutôt que de définir dynamiquement une variable et de l'utiliser à mon avis, j'ai constaté que j'étais en mesure de masquer ou d'afficher le sélecteur de date de cette façon:

struct ContentView : View {
    @State var showDatePicker = true
    @State var datePickerDate: Date = Date()

    var body: some View {
        VStack {
            if self.showDatePicker {
                DatePicker($datePickerDate)
            } else {
                DatePicker($datePickerDate).hidden()
            }
        }
    }
}

Ou, éventuellement, sans inclure le sélecteur de date au lieu de le masquer:

struct ContentView : View {
    @State var showDatePicker = true
    @State var datePickerDate: Date = Date()

    var body: some View {
        VStack {
            if self.showDatePicker {
                DatePicker($datePickerDate)
            }
        }
    }
}
21
Jake

J'ai créé une extension, vous pouvez donc utiliser un modificateur, comme ça pour masquer la vue:

Text("Hello World!")
    .isHidden(true)

Ou pour un retrait complet:

Text("Label")
    .isHidden(true, remove: true)

Le code source avec un exemple de projet est disponible sur GitHub ici: George-J-E/HidingViews .


Voici le code pour créer le ViewModifier:

Je vous recommande d'utiliser ce code dans son propre fichier (n'oubliez pas de 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.
    func isHidden(_ hidden: Bool, remove: Bool = false) -> some View {
        modifier(HiddenModifier(isHidden: hidden, remove: remove))
    }
}


/// Creates a view modifier to show and hide a view.
///
/// Variables can be used in place so that the content can be changed dynamically.
fileprivate struct HiddenModifier: ViewModifier {

    private let isHidden: Bool
    private let remove: Bool

    init(isHidden: Bool, remove: Bool = false) {
        self.isHidden = isHidden
        self.remove = remove
    }

    func body(content: Content) -> some View {
        Group {
            if isHidden {
                if remove {
                    EmptyView()
                } else {
                    content.hidden()
                }
            } else {
                content
            }
        }
    }
}
18
George_E

Vous pouvez définir l'alpha à la place, cela préservera également l'espace de mise en page de la vue et ne vous obligera pas à ajouter des vues factices comme les autres réponses:

struct ContentView : View {
    @State var showDatePicker = true
    @State var datePickerDate: Date = Date()

    var body: some View {
        VStack {
            DatePicker($datePickerDate)
            .opacity(showDatePicker ? 1 : 0)
        }
    }
}

J'espère que le modificateur hidden obtiendra un argument plus tard.

9
Mojtaba Hosseini

Commande-cliquez sur la vue en question et sélectionnez l'option Rendre conditionnel dans la version bêta 5. Je l'ai fait sur l'une de mes vues (LiftsCollectionView), et cela a généré ce qui suit:

    if suggestedLayout.size.height > 150 {
      LiftsCollectionView()
    } else {
      EmptyView()
    }
3
Justin Ekins

Vous avez également le modificateur opacity sur n'importe quel View:

ActivityIndicator(tint: .black)
   .opacity(self.isLoading ? 1.0 : 0.0)
0
PiKey