SwiftUI -在长按手势上增加数字,然后在手势释放后停止

xqkwcwgp  于 2023-05-16  发布在  Swift
关注(0)|答案(1)|浏览(155)

我正在尝试创建一个步进器,其中一个数字在长按手势上快速递增,并在用户释放时停止。
到目前为止,我在longPress上获得了增量,但是当我释放计时器时,计时器仍然会继续,继续增加状态。
我可以做些什么来解决这个问题,当用户释放按下,计时器停止。

struct CustomFoodItemView: View {
    @State var foodName = ""
    @State var proteinAmount = 1
    @State var carbAmount = 1
    @State var fatAmount = 1
    
    @State private var timer: Timer?
    @State var isLongPressing = false
    
    var body: some View {
        VStack{
            
            VStack{
                Text("Food Name")
                TextField("", text: $foodName)
                    .multilineTextAlignment(.center)
                    .border(.white)
                    .padding(.trailing, 10)
                    .frame(width:100, height:10)
            }
            HStack{
                Text(String(proteinAmount) + "g")
                    .frame(width:50, height:50)
                
                Image(systemName: "plus.circle.fill")
                    .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 30, height: 30)
                        .foregroundColor(Color("SuccessButtonColor"))
                        .simultaneousGesture(LongPressGesture(minimumDuration: 0.2).onChanged { _ in
                                      print("long press")
                                      self.isLongPressing = true
                            if self.isLongPressing == true{
                                self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { _ in
                                    proteinAmount += 1
                                })
                            } 
                                  }
                                .onEnded { _ in
                            print("stopped") //why won't you stop
                                    self.isLongPressing = false
                                })
                       }
              }

svujldwt

svujldwt1#

两件事:
1.你根本没有停止计时器,要停止它,你必须使它无效(正如Leo提到的)。你可以用self.timer?.invalidate()来实现。
1.当按下按钮的时间超过minimumDuration时间时识别到LongPressGesture时,将调用LongPressGesture.onEnded,它不处理释放按钮时的事件。所以你不想停止.onEnded上的计时器。

组合长按和拖动手势

我尝试了你的代码,一种方法是使用LongPressGesture来启动计时器,并使用最小距离为0的DragGesture来识别按钮释放。
这看起来像:

struct CustomFoodItemView: View {
    @State var foodName = ""
    @State var proteinAmount = 1
    @State var carbAmount = 1
    @State var fatAmount = 1
    
    @State private var timer: Timer?
    
    var body: some View {
        
        // a drag gesture that recognizes the release of the button to stop the timer, set minimumDistance to 0 to ensure no dragging is required
        let releaseGesture = DragGesture(minimumDistance: 0)
            .onEnded { _ in
                self.timer?.invalidate()
                print("Timer stopped")
            }
        
        // a long press gesture to activate timer and start increasing the proteinAmount
        let longPressGestureIncrease = LongPressGesture(minimumDuration: 0.2)
            .onEnded { value in
                self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { _ in
                    proteinAmount += 1
                })
                print("Timer started")
            }

        // a long press gesture to activate timer and start decreasing the proteinAmount
        let longPressGestureDecrease = LongPressGesture(minimumDuration: 0.2)
            .onEnded { value in
                self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { _ in
                    proteinAmount -= 1
                })
                print("Timer started")
            }
    
        // a combined gesture that forces the user to long press before releasing for increasing the value
        let combinedIncrease = longPressGestureIncrease.sequenced(before: releaseGesture)
    
        // a combined gesture that forces the user to long press before releasing for decreasing the value
        let combinedDecrease = longPressGestureDecrease.sequenced(before: releaseGesture)
        
        VStack{
            
            VStack{
                Text("Food Name")
                TextField("", text: $foodName)
                    .multilineTextAlignment(.center)
                    .border(.white)
                    .padding(.trailing, 10)
                    .frame(width:100, height:10)
            }
            HStack{
                Image(systemName: "minus.circle.fill")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 30, height: 30)
                    .foregroundColor(.red)
                    .gesture(combinedDecrease)

                Text(String(proteinAmount) + "g")
                    .frame(width:50, height:50)
                
                Image(systemName: "plus.circle.fill")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 30, height: 30)
                    .foregroundColor(.red)
                    .gesture(combinedIncrease)
            }
        }
    }
}

请查看包含代码片段中的几个项目的gif(开始长按后数字增加,释放“+”按钮时停止):

相关问题