Как сделать поворотный вид с SwiftUI - PullRequest
0 голосов
/ 16 октября 2019

Я попытался создать представление SWIFTUI, которое позволяет выполнять действие, аналогичное движению карты, с помощью метода gest (). Но я не могу придумать, как сделать так, чтобы просмотр был одним за другим. В настоящее время, когда я провожу пальцем, все представления исчезли

import SwiftUI

struct EventView: View {
    @State private var offset: CGSize = .zero
    @ObservedObject var randomView: EventViewModel
    var body: some View {
        ZStack{
            ForEach(randomView.randomViews,id:\.id){ view in
            view
                .background(Color.randomColor)
                .cornerRadius(8)
                .shadow(radius: 10)
                .padding()
                .offset(x: self.offset.width, y: self.offset.height)
                .gesture(
                    DragGesture()
                        .onChanged { self.offset = $0.translation }
                        .onEnded {
                            if $0.translation.width < -100 {

                                self.offset = .init(width: -1000, height: 0)
                            } else if $0.translation.width > 100 {
                                self.offset = .init(width: 1000, height: 0)

                            } else {
                                self.offset = .zero
                            }
                    }
                )
                .animation(.spring())
            }
        }
    }
}

struct EventView_Previews: PreviewProvider {
    static var previews: some View {
        EventView(randomView: EventViewModel())
    }
}

struct PersonView: View {
    var id:Int = Int.random(in: 1...1000)
    var body: some View {
        VStack(alignment: .center) {
            Image("testBtn")
                .clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/)

            Text("Majid Jabrayilov")
                .font(.title)
                .accentColor(.white)

            Text("iOS Developer")
                .font(.body)
                .accentColor(.white)
        }.padding()
    }
}

С этим фрагментом кода, когда я проведу пальцем, все исчезло

1 Ответ

1 голос
/ 16 октября 2019

По сути, ваш код говорит каждому представлению следовать за смещением, в то время как на самом деле вам нужно только верхнее движение. Итак, во-первых, я бы добавил переменную, которая будет хранить текущий индекс карты, и метод для вычисления ее смещения:

@State private var currentCard = 0

func offset(for i: Int) -> CGSize {
   return i == currentCard ? offset : .zero
}

Во-вторых, я обнаружил, что если мы просто оставим это так, наследующий вид касания получит смещение последнего (-1000, 0) и только затем перейдет в правильное местоположение, так что это выглядит так, как будто предыдущая карта решила вернуться вместо новой. Чтобы это исправить, я добавил флаг, отмечающий, что карта только что ушла, поэтому, когда мы снова ее трогаем, она сначала попадает в нужное место. Обычно мы делаем это в состоянии жеста .began, но у нас нет аналога для этого в swiftUI, поэтому единственное место, где это можно сделать, находится в .onChanged:

@State private var didJustSwipe = false

DragGesture()
    .onChanged {
        if self.didJustSwipe {
            self.didJustSwipe = false
            self.currentCard += 1
            self.offset = .zero
        } else {
            self.offset = $0.translation
        }
    }

In.onEnded в случае успеха мы присваиваем didJustSwipe = true

Так что теперь это работает отлично. Также я предлагаю вам погрузить ваш код в более мелкие части. Это не только улучшит читабельность, но и сэкономит время компиляции. Вы не предоставили реализацию EventViewModel и тех randomViews, поэтому я использовал вместо этого прямоугольники. Вот ваш код:

struct EventView: View {

    @State private var offset: CGSize = .zero
    @State private var currentCard = 0
    @State private var didJustSwipe = false

    var randomView: some View {
        return Rectangle()
            .foregroundColor(.green)
            .cornerRadius(20)
            .frame(width: 300, height: 400)
            .shadow(radius: 10)
            .padding()
            .opacity(0.3)
    }

    func offset(for i: Int) -> CGSize {
        return i == currentCard ? offset : .zero
    }

    var body: some View {
        ZStack{
            ForEach(currentCard..<5, id: \.self) { i in
                self.randomView
                    .offset(self.offset(for: i))
                    .gesture(self.gesture)
                    .animation(.spring())
            }
        }
    }

    var gesture: some Gesture {
        DragGesture()
            .onChanged {
                if self.didJustSwipe {
                    self.didJustSwipe = false
                    self.currentCard += 1
                    self.offset = .zero
                } else {
                    self.offset = $0.translation
                }
        }
            .onEnded {
                let w = $0.translation.width
                if abs(w) > 100 {
                    self.didJustSwipe = true
                    let x = w > 0 ? 1000 : -1000
                    self.offset = .init(width: x, height: 0)
                } else {
                    self.offset = .zero
                }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...