Search code examples
swiftswiftuistatusbar

Status bar length


I have a status bar that I made based on Ali's answer here: I shortened the appearance of the left hand side of the status bar by changing the circles trim from 0.3 to 0.35 so that it does not interfere by appearing over my labels. I would like to shorten the right hand side as well but do not understand what CGFloat(self.progress) is and how to shorten it without causing any issues with showing the correct progress being made. How do I shorten the appearance of the right hand side of the progress bar?

struct ProgressBar: View {
            @Binding var progress: Float
            
            var body: some View {
                VStack{
                    Label("Address: 0000", systemImage: "target")
                        .foregroundColor(Color(hex: "8f8f8f"))
                ZStack {
                    
                    Circle()
                        .trim(from: 0.35, to: 0.85)
                        .stroke(style: StrokeStyle(lineWidth: 12.0, lineCap: .round, lineJoin: .round))
                        .opacity(0.3)
                        .foregroundColor(Color.gray)
                        .rotationEffect(.degrees(54.5))
                    
                    Circle()
                        .trim(from: 0.35, to: CGFloat(self.progress))
                        .stroke(style: StrokeStyle(lineWidth: 12.0, lineCap: .round, lineJoin: .round))
                        .fill(AngularGradient(gradient: Gradient(stops: [
                            .init(color: Color.init(hex: "daff00"), location: 0.39000002),
                            //.init(color: Color.init(hex: "E59148"), location: 0.48000002),
                            .init(color: Color.init(hex: "00ff04"), location: 0.5999999),
                            //.init(color: Color.init(hex: "EEED56"), location: 0.7199998),
                            .init(color: Color.init(hex: "32E1A0"), location: 0.8099997)]), center: .center))
                        .rotationEffect(.degrees(54.5))
                    
                    VStack{
                        
                        
                        Text("824").font(Font.system(size: 44)).bold().foregroundColor(Color.init(hex: "ffffff"))
                        //Text("Please standby...").bold().foregroundColor(Color.init(hex: "FF6600"))
                        
                        Label("Please standby...", systemImage: "clock")
                            .foregroundColor(Color(hex: "FF6600"))
                        Label("Uploading memory model to controller", systemImage: "")
                            .foregroundColor(Color(hex: "8f8f8f"))
                        
                    }
                    }
                    
                }
                
            }
            
        }
        
        
        struct ProgressBarTriangle: View {
            @Binding var progress: Float
            
            
            var body: some View {
                ZStack {
                    Image("triangle").resizable().frame(width: 10, height: 10, alignment: .center)
                }
            }
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    
    extension Color {
        init(hex: String) {
            let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
            var int: UInt64 = 0
            Scanner(string: hex).scanHexInt64(&int)
            let a, r, g, b: UInt64
            switch hex.count {
            case 3: // RGB (12-bit)
                (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
            case 6: // RGB (24-bit)
                (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
            case 8: // ARGB (32-bit)
                (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
            default:
                (a, r, g, b) = (1, 1, 1, 0)
            }
            
            self.init(
                .sRGB,
                red: Double(r) / 255,
                green: Double(g) / 255,
                blue:  Double(b) / 255,
                opacity: Double(a) / 255
            )
        }
        
    }
    

Solution

  • There are two circle views, the first one is the background (grey) and the second one is the progress. Both circles have the trim function which is used to hide part of the view, and both should have the same values. Since the second circle is the progress it uses the progress variable and updates the to value of the trim, the problem is that for the view to work correctly the progress needs to have a maximum value of 0.85 to match the first circle. An approach to this is to make the progress var have a percentage value from 0 to 1 and them convert this progress to a CGFloat in with 0% is 0.35 and 100% is 0.85 to match the first circle: .trim(from: 0.35, to: 0.35 + (0.5 * CGFloat(self.progress)))

    Example:

    struct ProgressBar: View {
        @State var progress: Float = 0
        let leftHandSide: CGFloat = 0.35
        let rightHandSide: CGFloat = 0.5
        
        var body: some View {
            VStack{
                Label("Address: 0x1c000", systemImage: "target")
                    .foregroundColor(Color(hex: "8f8f8f"))
            ZStack {
                
                Circle()
                    .trim(from: leftHandSide, to: rightHandSide)
                    .stroke(style: StrokeStyle(lineWidth: 12.0, lineCap: .round, lineJoin: .round))
                    .opacity(0.3)
                    .foregroundColor(Color.gray)
                    .rotationEffect(.degrees(54.5))
                
                Circle()
                    .trim(from: leftHandSide, to: leftHandSide + ((rightHandSide - leftHandSide) * CGFloat(self.progress)))
                    .stroke(style: StrokeStyle(lineWidth: 12.0, lineCap: .round, lineJoin: .round))
                    .fill(AngularGradient(gradient: Gradient(stops: [
                        .init(color: Color.init(hex: "daff00"), location: 0.39000002),
                        //.init(color: Color.init(hex: "E59148"), location: 0.48000002),
                        .init(color: Color.init(hex: "00ff04"), location: 0.5999999),
                        //.init(color: Color.init(hex: "EEED56"), location: 0.7199998),
                        .init(color: Color.init(hex: "32E1A0"), location: 0.8099997)]), center: .center))
                    .rotationEffect(.degrees(54.5))
                
                VStack{
                    
                    
                    Text("824").font(Font.system(size: 44)).bold().foregroundColor(Color.init(hex: "ffffff"))
                    //Text("Please standby...").bold().foregroundColor(Color.init(hex: "FF6600"))
                    
                    Label("Please standby...", systemImage: "clock")
                        .foregroundColor(Color(hex: "FF6600"))
                    Label("Uploading memory model to controller", systemImage: "")
                        .foregroundColor(Color(hex: "8f8f8f"))
                    
                }
            }
                
                Button("Increase") {
                    self.progress = min(self.progress + 0.05, 1)
                }
                
                Button("Reset") {
                    self.progress = 0
                }
                
            }.frame(width: 300, height: 300)
            
        }
        
    }