【问题标题】:How to make a swipeable view with SwiftUI如何使用 SwiftUI 制作可滑动的视图
【发布时间】:2019-10-16 11:13:33
【问题描述】:

我尝试制作一个 SWIFTUI 视图,通过使用gesture() 方法允许像刷卡一样的操作。但我想不出一种方法让视图一个一个地滑动。目前,当我滑动所有视图时,所有视图都消失了

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()
    }
}

有了这段代码,当我刷卡时,整个东西都消失了

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    基本上你的代码告诉每个视图跟随偏移,而实际上你只想要最上面的一个移动。所以首先我要添加一个变量来保存卡片的当前索引和一个计算它的偏移量的方法:

    @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
            }
        }
    
    

    .onEnded成功的情况下我们分配didJustSwipe = true

    所以现在它完美地工作了。我还建议您将代码分成更小的部分。它不仅可以提高可读性,还可以节省一些编译时间。您没有提供EventViewModelrandomViews 的实现,所以我使用了矩形。这是你的代码:

    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
                    }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多