简体   繁体   English

SwiftUI:如果已满 (100%),如何创建带有“淡出”起始行的圆形“进度”条小部件,如 iOS 上的“电池”小部件

[英]SwiftUI: How to create circular "progress" bar widget with a "fade out" start line if it is full (100%), like the "battery" widget on iOS

I am creating my own "circular" progress bar widget in SwiftUI and I am wondering how to approach implementing he following.我正在 SwiftUI 中创建自己的“圆形”进度条小部件,我想知道如何实现他所关注的。 If the circle progress is at 100% (meaning the circle if full) I want the "start" of the line to have a "faded out" effect, so that the start and end of the line do not "merge".如果圆圈进度为 100%(表示圆圈已满),我希望线的“开始”具有“淡出”效果,以便线的开始和结束不会“合并”。 I saw this in the "battery" widgets on iOS. Here is a an example of "full" and "not full" battery widget:我在 iOS 的“电池”小部件中看到了这一点。这是“充满”和“未充满”电池小部件的示例:

在此处输入图像描述 在此处输入图像描述

Here is my current widget code:这是我当前的小部件代码:

struct CircleProgressView: View {
    
    @Binding var progress: Float
    
    var body: some View {
        ZStack {
            Circle()
                .stroke(lineWidth: 10)
                .opacity(0.3)
                .foregroundColor(Color(UIColor.systemGray3))
            
            Circle()
                .trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
                .stroke(style: StrokeStyle(lineWidth: 10, lineCap: .round, lineJoin: .round))
                .foregroundColor(Color(UIColor.systemGreen))
                .rotationEffect(Angle(degrees: 270.0))
        }
        .padding()
    }
}

Any ideas will be helpful.任何想法都会有所帮助。

Here is an approach.这是一种方法。 I stacked 4 circles:我叠了 4 个圆圈:

  • the grey base灰色基地
  • one first green circle to receive the shadow第一个绿色圆圈接收阴影
  • one circle clipped to a dot with shadow + clipshape to get rid of shadows on the sides of the circle一个圆圈用 shadow + clipshape 剪裁成一个点,以消除圆圈两侧的阴影
  • another green circle to cover the shadow on one side另一个绿色圆圈覆盖一侧的阴影

Here is the code:这是代码:

struct CircleProgressView: View {
    
    @Binding var progress: Float
    
    var body: some View {
        ZStack {
            // grey background circle
            Circle()
                .stroke(lineWidth: 30)
                .opacity(0.3)
                .foregroundColor(Color(UIColor.systemGray3))

            // green base circle to receive shadow
            Circle()
                .trim(from: 0.0, to: CGFloat(min(self.progress, 0.5)))
                .stroke(style: StrokeStyle(lineWidth: 30, lineCap: .round, lineJoin: .round))
                .foregroundColor(Color(UIColor.systemGreen))
                .rotationEffect(Angle(degrees: 270.0))

            // point with shadow, clipped
            Circle()
                .trim(from: CGFloat(abs((min(progress, 1.0))-0.001)), to: CGFloat(abs((min(progress, 1.0))-0.0005)))
                .stroke(style: StrokeStyle(lineWidth: 30, lineCap: .round, lineJoin: .round))
                .foregroundColor(Color(UIColor.blue))
                .shadow(color: .black, radius: 10, x: 0, y: 0)
                .rotationEffect(Angle(degrees: 270.0))
                .clipShape(
                    Circle().stroke(lineWidth: 30)
                )
            
            // green overlay circle to hide shadow on one side
            Circle()
                .trim(from: progress > 0.5 ? 0.25 : 0, to: CGFloat(min(self.progress, 1.0)))
                .stroke(style: StrokeStyle(lineWidth: 30, lineCap: .round, lineJoin: .round))
                .foregroundColor(Color(UIColor.systemGreen))
                .rotationEffect(Angle(degrees: 270.0))


            
        }
        .padding()
    }
}

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM