Comment désactiver l'animation dans la liste lorsque des changements d'objet observés dans SwiftUI?

15

Comment désactiver l'animation lorsque les données du modèle sont modifiées?

J'ai le code suivant:

struct FormView: View {

    @ObservedObject var viewModel: FormViewModel

    var body: some View {
        List {
            ForEach(viewModel.options) { option in
                Text(option.displayValue)
            }
        }
    }
}

Chaque changement de modèle de vue Listest mis à jour avec une animation.
Comment puis-je le désactiver?
J'ai essayé d'ajouter .animation(nil)mais ça n'aide pas

0rt
la source

Réponses:

1

La solution de contournement jusqu'à ce qu'Apple nous donne un changement pour le faire sur List est d'appeler List.id (_ :) Cela change l'état interne de List et force la List à recréer immédiatement, sans aucune animation. Pour plus de détails, voir Liste des problèmes d'animation de rechargement

La même chose pourrait être faite sur n'importe quelle vue (func id () fait partie du protocole View), mais vous devez savoir que toutes les variables d'état auront un état "par défaut" initial, alors utilisez-le avec précaution. C'est la même chose que "recréer" la vue.

Pour pouvoir comprendre comment cela fonctionne, voir https://swiftui-lab.com/swiftui-id/

user3441734
la source
1

La solution que j'ai trouvée est d'ajouter un identifiant unique qui change à chaque fois, donc il reconstruira la liste à chaque fois sans animation. Vérifié sur iOS 13.4.

var body: some View {
    List {
        ForEach(viewModel.options) { option in
            Text(option.displayValue)
        }
    }
    .id(UUID()) // no animation
}
Burgler-dev
la source
-3
  1. Il n'est pas nécessaire d'utiliser ForEach à l'intérieur de List au cas où vous ne l'utilisez pas Section. Donc au lieu de:

    List {
        ForEach(viewModel.options) { option in
            Text(option.displayValue)
        })
    }

    Le code suivant suffit pour écrire:

    List(viewModel.options) { option in
        Text(option.displayValue)
    }

    Et aussi mieux de savoir que l'utilisation de ForEach peut créer des problèmes, comme par exemple: SwiftUI: est-il possible d'utiliser ForEach + ContextMenu?

  2. Dans le cas où vous utiliserez seulement ForEach()ou seulement List()+ .animation(nil)- vous devez résoudre votre problème:

    Échantillon 1:

    ForEach(viewModel.options) { option in
        Text(option.displayValue)
    }.animation(nil)

    Échantillon 2:

    List(viewModel.options) { option in
        Text(option.displayValue)
    }.animation(nil)

    J'ai été testé à la fois sur macOS 10.15.2 (19C57) et cela fonctionne parfaitement.

  3. Vous pouvez également essayer d'utiliser .animation(nil)sur Listet les ForEachdeux. Je n'ai pas essayé ... mais je pense que cela vous donnera également l'effet nécessaire.

    List {
        ForEach(viewModel.options) { option in
            Text(option.displayValue)
        }.animation(nil)
    }.animation(nil)
Andrew
la source
.animation(nil)semble n'avoir aucun effet sur 13.3, malheureusement
Fabian Streitel
@FabianStreitel J'ai testé la partie 2 sur macOS 10.15.2 (19C57) et cela fonctionne parfaitement.
Andrew
Et j'ai testé les trois variantes sur iOS 13.3 (comme indiqué dans mon commentaire ci-dessus) et aucune d'entre elles ne modifie le comportement de la liste. OP n'a pas indiqué si elle créait une application iOS ou macOS, malheureusement. Mais je pense que les informations selon lesquelles cela ne fonctionne pas sur iOS sont également pertinentes pour les autres.
Fabian Streitel