Stack feature not working as per plan.

Good Morning/Afternoon/Evening.

I'm trying to build a code with a background bar (grey) and above it, we have a ProgressiveBar that starts full and empties as time passes.

To be able to stack the elements one above the other I'm trying to use the Zstack function, as shown on the code below, but when simulating the code the progressiveBar is always, on the iPhone screen, showing on top of the background bar, and not above as desired.

Could you please review the code below and let me know what I'm missing?

`var body: some View { ZStack(alignment: .leading) { // Background bar RoundedRectangle(cornerRadius: 10) .fill(Color.gray.opacity(0.3)) .frame(height: barHeight) // Set height to the specified barHeight

        // Progress bar
        GeometryReader { geometry in
            RoundedRectangle(cornerRadius: 10)
                .fill(barColor)
                .frame(width: CGFloat(progress) * geometry.size.width, height: barHeight)
                .animation(.linear(duration: 1), value: progress)
        }
        .cornerRadius(10)
        
        // Icon and label
        HStack {
            Image(systemName: icon)
                .foregroundColor(.black)
                .font(.system(size: 28))  // Increased size
                .padding(.leading, 8)
            Spacer()
            Text(timeString(from: duration * Double(progress)))
                .foregroundColor(.black)
                .bold()
                .font(.system(size: 24))  // Increased size
                .padding(.trailing, 8)
        }
        .frame(width: UIScreen.main.bounds.width * 0.9, height: barHeight)
        .zIndex(1)  // Ensure the HStack is on top
    }
    .padding(.horizontal)
Answered by Claude31 in 799916022

And now with progress bar overlaying:

struct ContentView: View {
    
    let barHeight: CGFloat = 30
    let barColor = Color.gray
    let duration: Double = 10
    let icon = "globe"
    @State private var progress: CGFloat = 0

    var body: some View {
        ZStack(alignment: .leading) {
//        VStack {
            // Background bar RoundedRectangle(cornerRadius: 10)
            //    .fill(Color.gray.opacity(0.3))
            //     .frame(height: barHeight)
            
            // Set height to the specified barHeight
            // Progress bar
//            GeometryReader { geometry in
            RoundedRectangle(cornerRadius: 10)
                .fill(barColor.opacity(0.5))    // To see through
                .frame(width: CGFloat(progress) * UIScreen.main.bounds.width, height: barHeight)
            //  .frame(width: CGFloat(progress) * geometry.size.width, height: barHeight)
                .animation(.linear(duration: 10), value: progress)
            // }
//                .cornerRadius(10) // That's redundant

            // Icon and label
            HStack {
                Rectangle() // to avoid frame moving when  animation starts)
                    .fill(.clear)
                    .frame(width: UIScreen.main.bounds.width * 0.05, height: barHeight)
                Image(systemName: icon)
                    .foregroundColor(.black)
                    .font(.system(size: 28))  // Increased size
                    .padding(.leading, 8)
                    .onTapGesture {
                        progress = 1  // Added to see progress
                    }
               Spacer()
                Text(String/*timeString*/(format: "%.1f", /*from: */duration * Double(progress)))
                    .foregroundColor(.black)
                    .bold()
                    .font(.system(size: 24))  // Increased size
                    .padding(.trailing, 8)
            }
            
            .frame(width: UIScreen.main.bounds.width/* * 0.9*/, height: barHeight) // Changed to avoid frame moving when  animation starts
            .zIndex(1)  // Ensure the HStack is on top
            
            Spacer() // ADDED THIS
        }
        .padding(.horizontal)
    }
}

We get this during progress:

May be we could use overlay, but did not try.

What are: barHeight, barColor, progress, icon and duration?

Please format your code properly, as you have some code outside of the code block, making it impossible to figure out what your code should actually look like.

What is ProgressiveBar ? Is it

            RoundedRectangle(cornerRadius: 10)

What do you mean by above or on top. Please show what you get and what you want.

Why do you need geometry reader and not just set the zIndex of the progress bar ?

I edited your code to guess and complete missing parts:

struct ContentView: View {
    
    let barHeight: CGFloat = 30
    let barColor = Color.gray
    let duration: Double = 10
    let icon = "globe"
    @State private var progress = 0

    var body: some View {
        ZStack(alignment: .leading) {
            // Background bar RoundedRectangle(cornerRadius: 10)
            //    .fill(Color.gray.opacity(0.3))
            //     .frame(height: barHeight)
            
            // Set height to the specified barHeight
            // Progress bar
            GeometryReader { geometry in
                RoundedRectangle(cornerRadius: 10)
                    .fill(barColor)
                    .frame(width: CGFloat(progress) * geometry.size.width, height: barHeight)
                    .animation(.linear(duration: 10), value: progress)
            }
            .cornerRadius(10)
            
            // Icon and label
            HStack {
                Image(systemName: icon)
                    .foregroundColor(.black)
                    .font(.system(size: 28))  // Increased size
                    .padding(.leading, 8)
                    .onTapGesture {
                        progress = 10  // Added to see progress
                    }
               Spacer()
                Text(String/*timeString*/(format: "%.1f", /*from: */duration * Double(progress)))
                    .foregroundColor(.black)
                    .bold()
                    .font(.system(size: 24))  // Increased size
                    .padding(.trailing, 8)
            }
            .frame(width: UIScreen.main.bounds.width * 0.9, height: barHeight)
            .zIndex(1)  // Ensure the HStack is on top
        }
        .padding(.horizontal)
    }
}

The progressBar is above:

I changed ZStack to VStack and removing geometryReader and get this:

struct ContentView: View {
    
    let barHeight: CGFloat = 30
    let barColor = Color.gray
    let duration: Double = 10
    let icon = "globe"
    @State private var progress = 0

    var body: some View {
//        ZStack(alignment: .leading) {
        VStack {
            
            // Set height to the specified barHeight
            // Progress bar
//            GeometryReader { geometry in // REMOVED
            RoundedRectangle(cornerRadius: 10)
                .fill(barColor)
                .frame(width: CGFloat(progress) * UIScreen.main.bounds.width, height: barHeight) // WE CAN get screen width directly
            //  .frame(width: CGFloat(progress) * geometry.size.width, height: barHeight)
                .animation(.linear(duration: 10), value: progress)
            // }
                .cornerRadius(10)
            
            // Icon and label
            HStack {
                Image(systemName: icon)
                    .foregroundColor(.black)
                    .font(.system(size: 28))  // Increased size
                    .padding(.leading, 8)
                    .onTapGesture {
                        progress = 10  // Added to see progress
                    }
               Spacer()
                Text(String/*timeString*/(format: "%.1f", /*from: */duration * Double(progress)))
                    .foregroundColor(.black)
                    .bold()
                    .font(.system(size: 24))  // Increased size
                    .padding(.trailing, 8)
            }
            .frame(width: UIScreen.main.bounds.width * 0.9, height: barHeight)
            // .zIndex(1)  // Ensure the HStack is on top
            Spacer() // ADDED THIS
        }
        .padding(.horizontal)
    }
}

Is it what you are looking for ? If so, don't forget to close the thread by marking the answer as correct.

Accepted Answer

And now with progress bar overlaying:

struct ContentView: View {
    
    let barHeight: CGFloat = 30
    let barColor = Color.gray
    let duration: Double = 10
    let icon = "globe"
    @State private var progress: CGFloat = 0

    var body: some View {
        ZStack(alignment: .leading) {
//        VStack {
            // Background bar RoundedRectangle(cornerRadius: 10)
            //    .fill(Color.gray.opacity(0.3))
            //     .frame(height: barHeight)
            
            // Set height to the specified barHeight
            // Progress bar
//            GeometryReader { geometry in
            RoundedRectangle(cornerRadius: 10)
                .fill(barColor.opacity(0.5))    // To see through
                .frame(width: CGFloat(progress) * UIScreen.main.bounds.width, height: barHeight)
            //  .frame(width: CGFloat(progress) * geometry.size.width, height: barHeight)
                .animation(.linear(duration: 10), value: progress)
            // }
//                .cornerRadius(10) // That's redundant

            // Icon and label
            HStack {
                Rectangle() // to avoid frame moving when  animation starts)
                    .fill(.clear)
                    .frame(width: UIScreen.main.bounds.width * 0.05, height: barHeight)
                Image(systemName: icon)
                    .foregroundColor(.black)
                    .font(.system(size: 28))  // Increased size
                    .padding(.leading, 8)
                    .onTapGesture {
                        progress = 1  // Added to see progress
                    }
               Spacer()
                Text(String/*timeString*/(format: "%.1f", /*from: */duration * Double(progress)))
                    .foregroundColor(.black)
                    .bold()
                    .font(.system(size: 24))  // Increased size
                    .padding(.trailing, 8)
            }
            
            .frame(width: UIScreen.main.bounds.width/* * 0.9*/, height: barHeight) // Changed to avoid frame moving when  animation starts
            .zIndex(1)  // Ensure the HStack is on top
            
            Spacer() // ADDED THIS
        }
        .padding(.horizontal)
    }
}

We get this during progress:

May be we could use overlay, but did not try.

Stack feature not working as per plan.
 
 
Q