Как добавить переход для условно отображаемого представления в SwiftUI?

#ios #swift #swiftui

#iOS #swift #swiftui

Вопрос:

Как добавить переход для условно отображаемого представления внутри GroupedListStyle списка? для достижения чего-то подобного условию DatePicker из раздела «Не беспокоить» в настройках (см. GIF ниже).

Добавление transition и animation для условно отображаемого представления, похоже, не работает.

 if condition {
    Toggle(isOn: $foo) {
        HStack {
            Text("Foo")
        }
    }
    .transition(.opacity)
    .animation(.easeInOut)
    .toggleStyle(SwitchToggleStyle(tint: Color.red)
}
 

введите описание изображения здесь

Реализация на основе pawello2222

Анимация настолько плавная, особенно когда представление вот-вот исчезнет. Позиция перехода была анимирована с кадра 1 по 11, но внезапно исчезла с кадра 12 и далее.

введите описание изображения здесь

введите описание изображения здесь

Ответ №1:

Вот возможное решение, изменение опубликованного значения с помощью withAnimation

 class ContentViewModel : ObservableObject {
    @Published var isOn : Bool = false {
        didSet {
            withAnimation {
                if isOn {
                    showRow = true
                }
                else {
                    showRow = false
                }
            }
        }
    }
    
    @Published var showRow = false
}

struct ContentView: View {
    
    @ObservedObject var viewModel = ContentViewModel()
            
    var body: some View {
        
        List() {
            
            Text("Hello World")

            HStack() {
                Toggle("Test", isOn: $viewModel.isOn)
                    .toggleStyle(SwitchToggleStyle(tint: Color.red))
            }
            
            if (viewModel.showRow) {
                Text("Hello Second World")
            }
       }.listStyle(GroupedListStyle())
    }
}
 

Ответ №2:

Возможно, было бы лучше сохранить логику, связанную с анимацией (например withAnimation ), внутри представления.

Возможное решение — создать пользовательский Binding :

 struct ContentView: View {
    @StateObject var viewModel = ViewModel()

    var binding: Binding<Bool> {
        .init(get: {
            viewModel.showRow
        }, set: { newValue in
            withAnimation {
                viewModel.showRow = newValue
            }
        })
    }

    var body: some View {
        List {
            Text("Text")
            Toggle("Toggle", isOn: binding)
                .toggleStyle(SwitchToggleStyle(tint: Color.red))
            if viewModel.showRow {
                Text("Hidden Text")
            }
        }
        .listStyle(GroupedListStyle())
    }
}
 

Комментарии:

1. На самом деле это даже лучше. Гораздо лучше иметь withAnimation внутри представления вместо ViewModel. Идея с привязкой отличная.

2. Спасибо! в моем случае условно отображаемый вид находится внутри a Section , а анимация не такая гладкая, см. Gif в ответе выше.

3. не уверен, что это ошибка анимации SwiftUI, я проверил GIF @davidev, и его анимация кажется гладкой.