You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI如何使用Stack布局实现进度环居左、控件右对齐的UI效果

问题原因
  • 主视图容器嵌套逻辑错误:直接在CaloriesView的body下平行放置多个独立的ZStack、HStack,SwiftUI不会自动实现左右分栏排列,所有控件会默认挤在视图顶部出现堆叠错位。
  • 进度环尺寸硬编码不合理:当前ProgressRingView写死250*250宽高加额外padding,没有给右侧控件预留布局空间,极易出现尺寸溢出。
  • 控件未做分组对齐:所有标签控件没有放在统一容器内排版,也无外层带边框的卡片容器包裹,观感零散。
可直接运行的修正代码

主视图 CaloriesView 代码

import SwiftUI

struct CaloriesView: View {
    var body: some View {
        // 外层左右分栏容器
        HStack(spacing: 20) {
            // 左侧进度环区域
            ProgressRingView()
                .scaledToFit()
                .frame(width: 180)
            
            // 右侧控件组 垂直排列
            VStack(alignment: .leading, spacing: 24) {
                Label("Base Goals", systemImage: "folder.circle")
                    .font(.system(size: 20, weight: .semibold))
                
                HStack(spacing: 20) {
                    Label("Daily Limit", systemImage: "flag.fill")
                        .font(.system(size: 17, weight: .medium))
                    Label("Food", systemImage: "fork.knife")
                        .font(.system(size: 17, weight: .medium))
                }
                
                Label("Exercise Taken", systemImage: "figure.walk")
                    .font(.system(size: 17, weight: .medium))
            }
            .frame(maxWidth: .infinity, alignment: .leading)
        }
        .padding(24)
        // 带边框圆角的卡片样式
        .background(
            RoundedRectangle(cornerRadius: 16)
                .fill(.white)
        )
        .overlay(
            RoundedRectangle(cornerRadius: 16)
                .stroke(Color.gray.opacity(0.2), lineWidth: 1)
        )
        .shadow(color: .black.opacity(0.05), radius: 10, x: 0, y: 2)
        .padding(.horizontal, 16)
    }
}

struct CaloriesView_Previews: PreviewProvider {
  static var previews: some View {
     CaloriesView()
 }
}

进度环 ProgressRingView 修正代码

import SwiftUI 
struct ProgressRingView: View {
    @State var progress = 0.0
    let colors: [Color] = [.yellow, .red,.blue, .purple]

    var body: some View {
        ZStack{
            // 占位底环
            Circle()
                .stroke(lineWidth: 15)
                .foregroundColor(.gray)
                .opacity(0.1)
            
            // 彩色进度环
            Circle()
                .trim(from: 0.0, to: min(progress,1.0))
                .stroke(  
                    AngularGradient(
                        gradient: Gradient(colors: colors), 
                        center: .center,
                        startAngle: .degrees(0), 
                        endAngle: .degrees(360 + 45)
                    ),
                    style: StrokeStyle(lineWidth: 12, lineCap: .round, lineJoin: .round)
                )
                .rotationEffect((Angle(degrees: 270)))
                .animation(.easeInOut(duration: 1.0),value:progress)
                .onAppear{
                    progress=1
                }
            
            VStack(spacing:20)
            {
                VStack(spacing:5)
                {
                    Text("Calories")
                        .opacity(0.7)
                        .font(.footnote)
                    Text("1850")
                        .font(.title)
                        .fontWeight(.bold)
                }
                .padding(.top)
                
                VStack(spacing:5)
                {
                    Text("Remaining ")
                        .opacity(0.7)
                        .font(.footnote)
                    
                    Text("420")
                        .font(.title3)
                        .fontWeight(.bold)
                }
            }
        }
    }
}
                        
struct ProgressRingView_Previews: PreviewProvider {
    static var previews: some View {
        ProgressRingView()
    }
}
关键修改说明
  • 布局逻辑调整:用最外层HStack实现左右分栏,右侧用VStack统一收纳所有标签控件,设置左对齐和统一间距,从根源解决控件堆叠错位问题。
  • 卡片样式实现:通过background加圆角矩形填充、overlay加细边框、shadow加轻微阴影,实现带边框的美观容器效果,匹配MyFitnessPal类应用的卡片风格。
  • 尺寸适配优化:取消进度环硬编码的250尺寸和多余padding,改为180宽度+scaledToFit自适应,给右侧控件留足布局空间,不会出现屏幕溢出。
  • 细节优化:调整了标签字号粗细、进度环线宽、环内文本内容,修复了原代码里Import大小写错误、Rmaining拼写错误,替换了更匹配运动场景的系统图标。
效果参考
  • 原错误实现效果:
    当前错误实现截图
  • 目标参考风格:
    目标样式参考

内容的提问来源于stack exchange,提问作者dotnetdevcsharp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 17:36:28