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

SwiftUI中ScrollView与fixedSize修饰符的布局问题

问题解决:ScrollView展开时不挤压底部按钮

问题分析

你的问题根源在于ScrollView使用了.fixedSize(vertical: true)修饰符——这个属性会让ScrollView的高度完全跟随内容动态变化,当展开的内容高度超过屏幕剩余空间时,就会把底部的Add按钮挤出屏幕,而且因为ScrollView本身没有高度限制,也不会触发内部滚动。

解决方案

只需要调整两处:

  1. 移除ScrollView的.fixedSize(horizontal: false, vertical: true)
  2. 给ScrollView添加.frame(maxHeight: .infinity),让它占据VStack中除Add按钮外的所有可用空间,内容超出时ScrollView内部滚动,不会挤压底部按钮
  3. 移除VStack中的Spacer(),避免ScrollView被向上推挤

修改后的完整代码

struct ContentView: View {
    
    var body: some View {
        
        VStack(spacing: 8) {
            ScrollView {
                ExpandView()
            }
            .frame(maxHeight: .infinity) // 让ScrollView填充剩余空间
            Button {
                
            } label: {
                HStack {
                    Spacer()
                    Text("Add")
                    Spacer()
                }
                .background(Color.green)
            }
        }
        .frame(maxWidth: .infinity)
        // 可选:适配底部安全区,避免按钮被遮挡(iOS 15+可用)
        .padding(.bottom, UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0)
        
    }
}

struct ExpandView: View {
    var body: some View {
        VStack {
            Accordion(title: "Red", content: {
                Rectangle()
                    .fill(.red)
                    .frame(height: 600)
            })
            Accordion(title: "Blue", content: {
                Rectangle()
                    .fill(.blue)
                    .frame(height: 600)
            })
        }
    }
}

struct Accordion<Content: View>: View {
    @State var isExpand: Bool = false
    let title: String
    @ViewBuilder let content: Content
    
    var body: some View {
        VStack(spacing: 0) {
            Button(action: {
                withAnimation {
                    isExpand.toggle()
                }
            }, label: {
                HStack {
                    Spacer()
                    Text(title)
                    Spacer()
                }
            })
            .buttonStyle(.plain)
            .frame(height: 44)
            .background(Color.yellow)
            if isExpand {
                content
                    .padding(.horizontal, 12)
                    .transition(.move(edge: .top))
            }
        }
        .clipped()
    }
}

效果说明

修改后,ScrollView会自动占据Add按钮上方的所有可用空间,当展开的内容高度超过这个空间时,ScrollView会启用内部滚动,底部的Add按钮将始终固定在屏幕底部,不会被挤压出去。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 15:19:49