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

如何让展开后超出屏幕的DisclosureGroup自动上滚?

解决SwiftUI中DisclosureGroup展开时自动滚动到内容的问题

你遇到的核心问题是Form基于List实现,自带滚动容器,直接在外层套ScrollView会破坏原有格式,且无法关联内部滚动行为。正确做法是将ScrollViewReader直接包裹Form,监听内层DisclosureGroup的展开状态触发滚动。

修改后的完整代码

struct TestView: View
{
    @State private var sheetIsPresented: Bool = false
    @State private var outerDisclosureIsExpanded: Bool = false
    @State private var innerDisclosureIsExpanded: Bool = false
    
    var body: some View
    {
        Button
        {
            self.sheetIsPresented = true
        }
        label:
        {
            Label("Add Item", systemImage: "plus")
        }
        .sheet(isPresented: self.$sheetIsPresented)
        {
            VStack
            {
                // 用ScrollViewReader包裹Form,关联内部滚动容器
                ScrollViewReader { proxy in
                    Form
                    {
                        Section(header: Text("Section"))
                        {
                            DisclosureGroup("Outer Disclosure Group", isExpanded: self.$outerDisclosureIsExpanded)
                            {
                                ForEach(1...20, id: \.self)
                                {
                                    index in Text("Value \(index)")
                                }
                                DisclosureGroup("Inner Disclosure Group", isExpanded: self.$innerDisclosureIsExpanded)
                                {
                                    VStack {
                                        Text("Text")
                                        
                                        Button("Button")
                                        {
                                            print("Button Pressed")
                                        }
                                        .id("innerButton") // 给目标元素设置唯一ID
                                    }
                                }
                            }
                        }
                    }
                    .onChange(of: innerDisclosureIsExpanded) { newValue in
                        // 内层展开时触发滚动
                        if newValue {
                            withAnimation {
                                proxy.scrollTo("innerButton", anchor: .bottom)
                            }
                        }
                    }
                }
            }
        }
    }
}

关键修改说明

  • ScrollViewReader的位置:直接包裹Form,确保代理能正确控制Form内部的List滚动容器,不会破坏原生样式。
  • 监听展开状态:通过onChange仅在内层DisclosureGroup从折叠变为展开时触发滚动,避免无效操作。
  • 锚点选择:使用.bottom锚点可确保内层内容的底部(按钮)完全显示在屏幕内,避免被安全区遮挡;若需滚动到内层顶部,可将ID设置在内层VStack上,锚点改为.top。
  • 目标ID设置:给需要滚动到的元素设置唯一ID,保证滚动目标精准。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 10:13:15