Як відключити анімацію в списку, коли спостережувані зміни об'єкта в 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)але це не допомагає

Відповіді:


1

Вирішення проблем, поки Apple не дасть нам зміни, щоб зробити це у списку, - це виклик List.id (_ :) Це змінить внутрішній стан списку і змусить Список відтворити негайно, без анімації. Докладніше див. Перелік анімаційних глюків для перезавантаження

Те ж саме можна зробити в будь-якому представленні (функція id () є частиною протоколу View), але ви повинні знати, що всі змінні стану матимуть початковий стан "за замовчуванням", тому використовуйте його обережно. Це те саме, що "відтворити" Вид.

Щоб зрозуміти, як це працює, дивіться https://swiftui-lab.com/swiftui-id/


1

Я знайшов рішення - додавати унікальний ідентифікатор, який змінюється щоразу, тому він буде кожного разу перебудовувати список без анімації. Підтверджено на iOS 13.4.

var body: some View {
    List {
        ForEach(viewModel.options) { option in
            Text(option.displayValue)
        }
    }
    .id(UUID()) // no animation
}

-3
  1. Немає необхідності використовувати ForEach всередині списку, якщо ви не використовуєте Section. Тож замість:

    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 (як зазначено в моєму коментарі вище), і жоден з них взагалі не змінює поведінку списку. На жаль, OP не заявив, чи роблять вони додаток для iOS чи macOS. Але я думаю, що інформація про те, що вона не працює на iOS, є актуальною і для інших.
Фабіан Стрейтель

Нещодавно я тестував, .animation(nil)використовуючи Xcode 11.4 з iOS 13.4, і він працює для мене.
Сімен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.