如何在SwiftUI中创建显示当前电池电量的电池徽章

xsuvu9jc  于 2022-10-31  发布在  Swift
关注(0)|答案(1)|浏览(260)

我想做的事情与MacOSiOS设备上的电池徽章几乎完全相同。我尝试使用SFSymbols,但它只支持%0%25%50%75%100,但我想将电池徽章更新为当前电池电量。

我尝试在SFSymbols中使用battery.0图标,并将其与RoundedRectangle重叠,如下所示:

struct BatteryView : View {
    var body: some View {
            ZStack {
                Image(systemName: "battery.0")
                RoundedRectangle(cornerRadius: 15)
                    .foregroundColor(.green)
            }
    }
}

但是当我试图放大或缩小它时,它的行为真的很奇怪,因为RoundedRectangle
提前感谢!

dsekswqp

dsekswqp1#

这是我想到的:
据我所知,SFSymbols中的battery图标仅由3个元素组成:一个圆角矩形一个位于电池顶部的半圆形以及另一个指示当前电池电量的圆角矩形

第一个圆角矩形(电池盒)

struct BatteryView : View {
    var body: some View {
        GeometryReader { geo in
            RoundedRectangle(cornerRadius: 15)
                .stroke(lineWidth: 3)
       } 
   }
}

它看起来像这样(frame为180,60):

我只是按照你的建议用了一个圆角矩形的电池盒。

半圆

我为此创建了一个名为HalfCircleShape的简单形状。

struct HalfCircleShape : Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()

        path.move(to: CGPoint(x: rect.minX, y: rect.midY))
        path.addArc(center: CGPoint(x: rect.minX, y: rect.midY), radius: rect.height , startAngle: .degrees(90), endAngle: .degrees(270), clockwise: true)
        return path
    }
}

GeometryReader中,我给予了当前帧的1/7,因为它看起来很优雅。
我把这些和HStack结合起来

就像这样:

GeometryReader { geo in
    HStack {
        RoundedRectangle(cornerRadius: 15)
            .stroke(lineWidth: 3)

        HalfCircleShape()
            .frame(width: geo.size.width / 7, height: geo.size.height / 7)
    }
}

电池指示灯

我在Color中创建了一个扩展来选择当前电池电量的颜色

extension Color {
    static var BatteryLevel : Color {
        let batteryLevel = 0.6
        print(batteryLevel)
        switch batteryLevel {
            // returns red color for range %0 to %20
            case 0...0.2:
                return Color.red
            // returns yellow color for range %20 to %50
            case 0.2...0.5:
                return Color.yellow
            // returns green color for range %50 to %100
            case 0.5...1.0:
                return Color.green
            default:
                return Color.clear
        }
    }
}

我刚刚创建了另一个RoundedRectangle,并将两个RoundedRectangle合并为一个ZStack
结果如下所示:第一次
最终代码:

import SwiftUI

struct ContentView: View {
    var body: some View {
            BatteryView()
            .frame(width: 170, height: 60)
            .padding()
    }
}

struct HalfCircleShape : Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()

        path.move(to: CGPoint(x: rect.minX, y: rect.midY))
        path.addArc(center: CGPoint(x: rect.minX, y: rect.midY), radius: rect.height , startAngle: .degrees(90), endAngle: .degrees(270), clockwise: true)
        return path
    }
}

struct BatteryView : View {
    init() {
        UIDevice.current.isBatteryMonitoringEnabled = true
    }
    var body: some View {
        // UIDevice.current.batteryLevel always returns -1, and I don't know why. so here's a value for you to preview
        let batteryLevel = 0.4
        GeometryReader { geo in
            HStack(spacing: 5) {
                GeometryReader { rectangle in
                    RoundedRectangle(cornerRadius: 15)
                        .stroke(lineWidth: 3)
                    RoundedRectangle(cornerRadius: 15)
                        .padding(5)
                        .frame(width: rectangle.size.width - (rectangle.size.width * (1 - batteryLevel)))
                        .foregroundColor(Color.BatteryLevel)
                }
                HalfCircleShape()
                .frame(width: geo.size.width / 7, height: geo.size.height / 7)

            }
            .padding(.leading)
        }
    }
}

extension Color {
    static var BatteryLevel : Color {
        let batteryLevel = 0.4
        print(batteryLevel)
        switch batteryLevel {
            // returns red color for range %0 to %20
            case 0...0.2:
                return Color.red
            // returns yellow color for range %20 to %50
            case 0.2...0.5:
                return Color.yellow
            // returns green color for range %50 to %100
            case 0.5...1.0:
                return Color.green
            default:
                return Color.clear
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

此外,在UIDevice中,有一个名为batteryLevel的属性,它可以提供当前电池电量,但在本例中,它只返回-1,请注意:as discussed here,这似乎是Swift中的一个错误。

相关问题