Как отключить анимацию в списке при изменении наблюдаемого объекта в SwiftUI?

15

Как отключить анимацию при изменении данных модели просмотра?

У меня есть следующий код:

struct FormView: View {

    @ObservedObject var viewModel: FormViewModel

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

Каждый раз, когда изменения модели представления Listобновляются с анимацией.
Как я могу отключить это?
Я пытался добавить, .animation(nil)но это не помогает

0rt
источник

Ответы:

1

Обходной путь, пока Apple не предоставит нам возможность сделать это в List, - это вызов List.id (_ :). Он изменяет внутреннее состояние List и заставляет List воссоздавать немедленно, без какой-либо анимации. Подробнее см. Список перезагрузки анимации глюков

То же самое можно сделать с любым View (func id () является частью протокола View), но вы должны знать, что все переменные состояния будут иметь начальное состояние «по умолчанию», поэтому используйте его осторожно. Это то же самое, что «воссоздать» вид.

Чтобы понять, как это работает, см. Https://swiftui-lab.com/swiftui-id/.

user3441734
источник
1

Решение, которое я нашел, заключается в добавлении уникального идентификатора, который меняется каждый раз, поэтому он будет перестраивать список каждый раз без анимации. Проверено на iOS 13.4.

var body: some View {
    List {
        ForEach(viewModel.options) { option in
            Text(option.displayValue)
        }
    }
    .id(UUID()) // no animation
}
Burgler-DEV
источник
-3
  1. Нет необходимости использовать ForEach внутри List, если вы не используете Sections. Так что вместо:

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

    Для написания следующего кода достаточно:

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

    А также лучше знать, что использование ForEach может создать некоторые проблемы, например: SwiftUI: возможно ли использовать ForEach + ContextMenu?

  2. В случае, если вы будете использовать только ForEach()или только List()+ .animation(nil)- должны решить вашу проблему:

    Образец 1:

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

    Образец 2:

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

    Я был протестирован как на MacOS 10.15.2 (19C57), и он работает отлично.

  3. Кроме того, вы можете попробовать использовать .animation(nil)на Listи ForEachкак. Я не пытался ... но я думаю, что это также даст вам необходимый эффект.

    List {
        ForEach(viewModel.options) { option in
            Text(option.displayValue)
        }.animation(nil)
    }.animation(nil)
Эндрю
источник
.animation(nil)к 13.3, к сожалению, никак не влияет
Фабиан Штрайтель
@FabianStreitel Я тестировал часть 2 на macOS 10.15.2 (19C57), и она отлично работает.
Эндрю
И я тестировал все три варианта на iOS 13.3 (как указано в моем комментарии выше), и ни один из них не изменил поведение List вообще. ОП, к сожалению, не указала, делают ли они приложение для iOS или macOS. Но я думаю, что информация о том, что она не работает на iOS, актуальна и для других.
Фабиан Штрайтель