SwiftUI - Как изменить иерархическую позицию View? - PullRequest
0 голосов
/ 07 июня 2019

Вот базовый пример того, что не работает:

import SwiftUI

struct Test : View {
    @State var swapped = false

    var body: some View {
        if swapped { Color.green }
        Color.blue.tapAction {
            withAnimation { self.swapped.toggle() }
        }
        if !swapped { Color.green }
    }
}

SwiftUI не может выяснить, что я думаю о первом Color.green и втором Color.green как об одном и том же виде,поэтому, конечно, анимация просто затухает один из них, в то время как другой на новом месте.Я ищу способ указать SwiftUI, что это одно и то же представление, и анимировать его в новом месте.Я обнаружил модификатор .id() с большим волнением, потому что полагал, что он даст мне нужный мне эффект:

import SwiftUI

struct Test : View {
    @State var swapped = false

    var body: some View {
        if swapped { Color.green.id("green") }
        Color.blue.tapAction {
            withAnimation { self.swapped.toggle() }
        }
        if !swapped { Color.green.id("green") }
    }
}

Это, к сожалению, тоже не работает.Я невероятно взволнован SwiftUI, но мне кажется, что способность изменять структуру иерархии представлений при сохранении идентичности представлений весьма важна.Фактический вариант использования, который побудил меня задуматься над этим, заключается в том, что у меня есть несколько видов, для которых я пытаюсь создать фанатскую анимацию.Простейшим способом было бы поместить элементы в ZStack в одно состояние, чтобы они были все друг над другом, а затем поместить их в VStack в разнесенном состоянии, чтобы они были вертикальноразложить и все видно.Изменение с ZStack на VStack, конечно, считается изменением структуры, и поэтому вся преемственность между состояниями теряется, а все просто пересекается.Кто-нибудь знает, что с этим делать?

1 Ответ

0 голосов
/ 14 июня 2019

Я думаю, что у вас есть анимационная часть вашего вопроса, но, к сожалению, я не думаю, что она сохранит тот же экземпляр представления. Я попытался извлечь green в переменную, чтобы посмотреть, работает ли это, но если я правильно понимаю SwiftUI, это не означает, что один и тот же экземпляр представления будет разделен в двух местах.

Что я делаю, так это добавление перехода, когда зеленый вид добавлен / удален. Таким образом, представление перемещается в место его замены перед исчезновением.

struct Test : View {
    @State var swapped = false
    let green = Color.green

    var body: some View {
        HStack {
            if swapped {
                green
                    .transition(.offset(CGSize(width: 200, height: 0)))
                    .animation(.basic())
            }
            Color.blue.animation(.basic()).tapAction {
                withAnimation { self.swapped.toggle() }
            }
            if !swapped {
                green.transition(.offset(CGSize(width: -200, height: 0)))
                .animation(.basic())
            }
        }
    }
}

Это быстрое и грязное решение, в котором используются жестко запрограммированные значения в зависимости от размера портретного экрана iPhone 6/7/8

...