如何在SwiftUI中创建显示当前实时电量的电池徽章
实现实时电量的电池徽章解决方案
你遇到的问题核心是直接叠加的RoundedRectangle没有和电池图标做适配,缩放时尺寸、对齐逻辑混乱,导致显示异常。下面提供一个精准适配的实现方案,支持0-100%的实时电量显示,且缩放时表现稳定。
解决方案代码
struct BatteryView: View { var batteryLevel: Double // 传入0.0(空)到1.0(满)的电量百分比 // 适配电池图标的内部边距和圆角,可根据实际显示效果微调 private let batteryInnerInset: CGFloat = 4 private let fillCornerRadius: CGFloat = 3 var body: some View { ZStack(alignment: .leading) { GeometryReader { geo in // 电池轮廓图标,自动适配父视图尺寸 Image(systemName: "battery.0") .resizable() .scaledToFit() // 动态填充的电量矩形 RoundedRectangle(cornerRadius: fillCornerRadius) .foregroundColor(batteryColor) // 缩进以匹配电池内部的空白区域 .padding(batteryInnerInset) // 根据电量百分比计算填充宽度,减去双倍边距抵消左右padding的影响 .frame(width: max(0, geo.size.width * batteryLevel - batteryInnerInset * 2), alignment: .leading) .clipped() // 裁剪超出电池轮廓的部分 } } } // 根据剩余电量自动切换填充颜色,贴合系统视觉逻辑 private var batteryColor: Color { switch batteryLevel { case ...0.2: return .red case 0.2..<0.5: return .orange default: return .green } } } // 预览使用示例 struct BatteryView_Previews: PreviewProvider { static var previews: some View { VStack(spacing: 20) { BatteryView(batteryLevel: 0.0) .frame(width: 80, height: 40) BatteryView(batteryLevel: 0.3) .frame(width: 80, height: 40) BatteryView(batteryLevel: 0.75) .frame(width: 80, height: 40) BatteryView(batteryLevel: 1.0) .frame(width: 80, height: 40) } } }
方案说明
- 尺寸适配:通过
GeometryReader获取电池图标的实际渲染尺寸,确保填充矩形的宽度计算完全基于当前图标大小,缩放时不会错位。 - 精准对齐:使用
batteryInnerInset控制填充矩形与电池轮廓的间距,完美贴合图标内部的空白区域;fillCornerRadius匹配电池内部的圆角弧度,视觉上和系统图标一致。 - 动态电量支持:通过
batteryLevel参数直接控制填充宽度,支持0-100%的任意实时电量数值。 - 颜色逻辑:根据剩余电量自动切换填充色,低电量显示红色、中电量橙色、高电量绿色,符合用户的认知习惯。
原代码问题分析
- 未限制
RoundedRectangle的尺寸,缩放时会超出电池图标边界; - 没有对齐到电池内部区域,填充形状和轮廓不匹配;
- 未关联电量数值,无法实现实时电量显示。
内容的提问来源于stack exchange,提问作者user20346906
相关产品推荐
相关产品推荐

