はじめに
ゼンリーのアプリを見てたらバッテリー残量が表示されていたのでどうやるのかなと思い、試してみました。
せっかく試したので記事にしておきます。
これをちょっと変えてサンプルアプリを作成します。
サンプルアプリ
実装
View
import SwiftUI
struct ContentView: View {
@StateObject private var viewModel = ViewModel()
var body: some View {
batteryShape
.overlay(batteryText.foregroundColor(.white).blendMode(.difference))
.overlay(batteryText.blendMode(.hue))
.overlay(batteryText.foregroundColor(.white).blendMode(.overlay))
}
var batteryText: some View {
Text("\(Int(viewModel.batteryLevel))")
.font(.system(size: 70, weight: .black))
}
var batteryShape: some View {
ZStack(alignment: .center) {
RoundedRectangle(cornerRadius: 15)
.stroke(Color.black, lineWidth: 6)
.frame(width: 250, height: 120)
RoundedRectangle(cornerRadius: 10)
.foregroundColor(viewModel.batteryColor)
.frame(width: 230 * (viewModel.batteryLevel / 100), height: 100, alignment: .leading)
.alignmentGuide(HorizontalAlignment.center) { _ in 115 }
}
}
}
ViewModel
import Combine
import SwiftUI
final class ViewModel: ObservableObject {
@Published var batteryLevel: CGFloat = 100
@Published var batteryColor: Color = .black
private let device = UIDevice.current
private var cancellable = Set<AnyCancellable>()
init() {
device.isBatteryMonitoringEnabled = true
device.publisher(for: \.batteryState)
.sink { [weak self] status in
guard let self else { return }
switch status {
case .charging:
self.batteryColor = .green
case .unplugged:
self.batteryColor = .black
case .full:
self.batteryColor = .black
case .unknown:
self.batteryColor = .black
default:
self.batteryColor = .black
}
}
.store(in: &cancellable)
device.publisher(for: \.batteryLevel)
.map { CGFloat($0) * 100 }
.assign(to: &$batteryLevel)
}
}
おわり
充電中のテキストカラーが純粋な白にできなかったのが悔しいです。。。