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

SwiftUI Bottom Sheet小屏幕Spacer占用空间过大问题

SwiftUI Bottom Sheet在iPhoneSE上Spacer占用过多空间问题

我开发了一个SwiftUI Bottom Sheet视图,原本应该适配iPhoneSE,但其中的问题Spacer却毫无必要地占用了大量空间。尝试过给该Spacer添加.fixedSize()、调整minSize为2或0、设置视图优先级等操作,问题仍未解决。不同设置下的设备显示效果:

  • 添加.fixedSize():iPhone Pro Max显示正常,iPhone SE内容过于紧凑
  • 未添加.fixedSize():iPhone Pro Max显示正常,iPhone SE出现大量空白

相关代码

ExerciseSheet视图

struct ExerciseSheet: View {
    @StateObject var exerciseShetViewModel: ExerciseSheetViewModel = ExerciseSheetViewModel()
    
    var body: some View {
        GlassCard(backgroundImageName: "exerciseBackground") {
            
            VStack(alignment: .leading) {
                Group {
                    oneVerticalSpacer()
                    Text("Log Workout")
                        .Title2Bold()
                    
                    oneVerticalSpacer()
                }
                Group {
                    let exerciseTypebinding = Binding<ModelExerciseEventType?>(
                        get: { exerciseShetViewModel.state.activityType },
                        set: { exerciseShetViewModel.updateActivityType($0) }
                    )
                    CustomDropdown(
                        optionSelected: exerciseTypebinding,
                        title: "Activity Type",
                        options: ModelExerciseEventType.allCases
                    )
                    oneVerticalSpacer()
                    
                    if exerciseShetViewModel.state.activityType == .other {
                        let customNameBinding = Binding<String>(
                            get: { exerciseShetViewModel.state.customActivityName ?? "" },
                            set: { exerciseShetViewModel.updateCustomName($0) }
                        )
                        CustomTextfield(textInput: customNameBinding, title: "Activity Name")
                    }
                }
                
                Group {
                    let durationBinding = Binding<ModelDuration?>(
                        get: { exerciseShetViewModel.state.duration },
                        set: { exerciseShetViewModel.updateDuration($0) }
                    )
                    CustomDurationPicker(duration: durationBinding)
                    
                    oneVerticalSpacer()
                    
                    let distanceBinding = Binding<ModelDistance?>(
                        get: { exerciseShetViewModel.state.distance },
                        set: { exerciseShetViewModel.updateDistance($0) }
                    )
                    CustomDistanceField(distance: distanceBinding)
                }
                
                Group {
                    
                    let dateBinding = Binding<Date?>(
                        get: { exerciseShetViewModel.state.activityDate },
                        set: { exerciseShetViewModel.updateActivityDate($0) }
                    )
                    
                    CustomDatePicker(title: "Date", date: dateBinding, components: .date)
                    
                    oneVerticalSpacer()
                    
                    CustomDatePicker(
                        title: "Time of Day",
                        date: dateBinding,
                        style: .compact,
                        components: .hourAndMinute
                    )
                    
                    oneVerticalSpacer()
                }
                
                Group {
                    let caloriesBinding = Binding<String>(
                        get: { String(exerciseShetViewModel.state.calories ?? 0) },
                        set: { exerciseShetViewModel.updateCalories(Int($0))}
                    )
                    CustomTextfield(
                        textInput: caloriesBinding,
                        title: "Calories (Optional)",
                        keyboardType: .numberPad
                    )
                    
                    oneVerticalSpacer()
                    
                    let exertionBinding = Binding(
                        get: { exerciseShetViewModel.state.exertion },
                        set: { exerciseShetViewModel.updateExertion($0)}
                    )
                    CustomDropdown(
                        optionSelected: exertionBinding,
                        title: "Preceived Exertion (Optional)",
                        options: ModelPreceivedExertion.allCases
                    )
                }
                
                Spacer() // <---- 问题Spacer
                    .frame(minHeight: -1)
                
                HStack {
                    Spacer()
                    
                    CustomButton(
                        buttonTitle: "Ok",
                        buttonFrame: .small,
                        buttonAction: {}
                    )
                }
            }
        }.frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

GlassCard视图

struct GlassCard<Content: View>: View {
    let content: () -> Content
    let backgroundImageName: String?
    
    init(backgroundImageName: String? = nil, @ViewBuilder content: @escaping () -> Content) {
        self.content = content
        self.backgroundImageName = backgroundImageName
    }
    
    var body: some View {
        ZStack {
            if backgroundImageName != nil {
                Image(backgroundImageName!, bundle: .main)
                    .resizable()
                    .scaledToFill()
                    .blur(radius: 4.0)
            }
            
            ColorTheme.primaryCardColor
            
            content()
                .padding(SpacingTheme.one)
        }
        .clipShape(RoundedRectangle(cornerRadius: SpacingTheme.one))
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:03:09