SwiftUI 进度视图在单击“后退”时未启动进度

问题描述 投票:0回答:1

我有 swiftui 应用程序,其中添加了自定义进度条

struct ContentView: View {
    @State private var progress: CGFloat = 0.0
    @State private var isProgressActive = false
    @State private var isProgressCompleted = false // Track completion status
    @State var next: Bool = false

    var body: some View {
        NavigationStack {
            VStack(spacing: 20) {
                
                Button(action: {
                    print("start progress when clicked")
                    isProgressActive  = true
                }, label: {
                    Text("Start Progress")
                })
                
                Button(action: {
                    self.next = true
                }, label: {
                    Text("Next")
                })
                .navigationDestination(isPresented: $next, destination: {
                    SecondView()
                })
                
                CustomProgressBar(progress: $progress, isProgressActive: $isProgressActive, progressBarCallback: {
                    isProgressCompleted = true // Set progress completion status
                })
            }
            .padding()
        }
        /*.onChange(of: next) { _ in
            if !next {
                progress = 0.0 // Reset progress when returning from the next screen
                isProgressCompleted = false // Reset completion status
            }
        }
        .onAppear {
            if isProgressCompleted {
                progress = 0.0 // Set progress to completed state if it was completed before
            }
        }*/
    }
}

import SwiftUI
import Combine


struct CustomProgressBar: View {
    @Binding var progress: CGFloat
    @Binding var isProgressActive: Bool // Add binding to control progress activation
    var progressCompleted: () -> Void

    @State private var isCompleted = false
    private var timer: Publishers.Autoconnect<Timer.TimerPublisher>

    init(progress: Binding<CGFloat>, isProgressActive: Binding<Bool>, progressBarCallback: @escaping () -> Void) {
        self._progress = progress
        self._isProgressActive = isProgressActive // Initialize binding
        self.progressCompleted = progressBarCallback
        self.timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
    }

    var body: some View {
        ZStack(alignment: .leading) {
            RoundedRectangle(cornerRadius: 2.5) // Adjust corner radius as needed
                .frame(width: 300, height: 5)
                .opacity(0.3)
                .foregroundColor(.black) // Changed to .black for clarity

            RoundedRectangle(cornerRadius: 2.5) // Adjust corner radius as needed
                .frame(width: progress * 300, height: 5)
                .foregroundColor(.green)
                .animation(.easeInOut, value: progress)
        }
        .onReceive(timer) { _ in
            if isProgressActive { // Check if progress should be active
                if !isCompleted {
                    if progress < 1.0 {
                        progress += 0.01
                    } else {
                        isCompleted = true
                        self.progressCompleted()
                        timer.upstream.connect().cancel()
                        // Optionally handle completion
                    }
                }
            }
        }
    }
}
import SwiftUI

struct SecondView: View {
    var body: some View {
        Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
    }
}

单击“开始进度”按钮进度查看开始进度。当进度完成时,单击下一步按钮,然后在下一个屏幕中单击后退按钮。单击“后退”时,当我单击“开始进度”时,它不会再次开始进度。意味着进度视图在单击返回时不会重新加载。如何解决这个问题? 任何帮助将不胜感激。

ios swift swiftui progress-bar
1个回答
0
投票
  1. 首先,您确实使用
    cancel()
    停止了计时器。所以,之后,
    .onReceive(timer)
    无论如何都不会再执行了。
  2. 其次,我认为这里存在矛盾的状态,例如:
    isCompleted
    isProgressActive
    具有相反的含义。然而,当
    isCompleted = true
    时,也是
    isProgressActive = true
    。这是不正确的。

因此,应该是:

struct CustomProgressBar: View {
   ZStack(alignment: .leading) {
       ...
   }
   .onReceive(timer) { _ in
       ...
       if !isCompleted {
           ...
       } else {
           isCompleted = true
           isProgressActive = false //<- reset isProgressActive here
           timer.upstream.connect().cancel()
       }
   }
   .onChange(of: isProgressActive, { _, _ in
       //When progress reached its max value, reset the default state if
       //"start progress when clicked"
       if isCompleted && isProgressActive {
            isCompleted = false
            progress = 0.0

            timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
        }
   }
}
© www.soinside.com 2019 - 2024. All rights reserved.