SwiftUI — DisclosureGroup

SwiftUI 中,DisclosureGroup 是一个轻量级的折叠组件,允许用户显示或隐藏一组内容(通常用于折叠和展开的 UI 需求)。它可以通过一个标题和内容区域的组合来创建动态的 UI 视图。DisclosureGroup 特别适合用于导航控件、过滤器、分类设置等场景。

下面是对 DisclosureGroup 的详细介绍,包括其语法、功能和实际应用示例。


1. DisclosureGroup 的基本语法 #

DisclosureGroup 的基本结构如下:

DisclosureGroup(
    isExpanded: Binding<Bool>,  // 是否展开的绑定属性(用于控制组件状态,可选)
    content: () -> Content,      // 折叠内容
    label: () -> Label           // 标题
)

参数解释:

  • isExpanded (可选):
    • 可选的绑定变量,用于动态控制折叠和展开的状态。
    • 如果不提供,DisclosureGroup 会具有自己的内部状态。
  • content (必需):
    • 折叠组件内部的内容。
    • 这是组件在展开时显示的内容,可以包含任意 SwiftUI 视图。
  • label (必需):
    • 折叠组件的标题,是一个 View,比如文本、图标或自定义视图。

2. 使用示例 #

示例 1:基本用法 #

一个简单的 DisclosureGroup,使用默认的内部状态控制展开/折叠状态。

import SwiftUI

struct BasicDisclosureGroup: View {
    var body: some View {
        DisclosureGroup {
            Text("This is the detailed content.") // 折叠内容
        } label: {
            Text("Tap to Expand")                 // 标题
                .font(.headline)
                .foregroundColor(.blue)
        }
        .padding()
        .background(Color.gray.opacity(0.2))      // 设置背景颜色
        .cornerRadius(10)
    }
}

运行效果: #

  • 初始状态是收起的,标题显示为 “Tap to Expand”。
  • 点击标题会展开,显示内容 “This is the detailed content."。

示例 2:使用 Binding 动态控制折叠状态 #

可以通过绑定变量(@State)来控制 DisclosureGroup 的展开状态。

import SwiftUI

struct ControllableDisclosureGroup: View {
    @State private var isExpanded = false // 控制折叠状态

    var body: some View {
        VStack {
            DisclosureGroup(isExpanded: $isExpanded) {
                Text("Here is some more detailed information.")
                    .foregroundColor(.gray)
            } label: {
                HStack {
                    Image(systemName: isExpanded ? "chevron.down" : "chevron.right") // 动态图标
                    Text("Information")
                        .font(.headline)
                        .foregroundColor(.primary)
                }
            }
            .padding()
            .background(Color.blue.opacity(0.1))
            .cornerRadius(10)

            Button(action: {
                isExpanded.toggle() // 手动控制展开/折叠
            }) {
                Text(isExpanded ? "Collapse" : "Expand")
                    .foregroundColor(.white)
                    .padding()
                    .background(Color.blue)
                    .cornerRadius(10)
            }
        }
        .padding()
    }
}

功能: #

  • 点击按钮 ExpandCollapse 手动控制折叠状态。
  • 标题图标动态变化(使用 chevron.rightchevron.down 来表示折叠和展开状态)。

示例 3:多个折叠组件 #

在一个界面中可以组合多个 DisclosureGroup 来实现复杂的嵌套折叠。

import SwiftUI

struct NestedDisclosureGroup: View {
    var body: some View {
        DisclosureGroup {
            DisclosureGroup {
                Text("Item 1")
                Text("Item 2")
            } label: {
                Text("Subcategory 1")
            }

            DisclosureGroup {
                Text("Item A")
                Text("Item B")
            } label: {
                Text("Subcategory 2")
            }
        } label: {
            Text("Main Category")
                .font(.headline)
                .foregroundColor(.blue)
        }
        .padding()
        .background(Color.gray.opacity(0.2))
        .cornerRadius(10)
    }
}

运行效果: #

  • 最外层是 “Main Category”。
  • 点击 “Main Category” 会显示 “Subcategory 1” 和 “Subcategory 2”。
  • 每个子分类也可以进一步展开显示详细信息。

3. 定制 DisclosureGroup 的样式 #

虽然 DisclosureGroup 具有系统样式,但我们可以通过修饰符进一步定制其外观,比如背景颜色、字体样式等。

自定义样式示例 #

DisclosureGroup {
    Text("Customized Content")
        .padding()
        .background(Color.green.opacity(0.2))
} label: {
    HStack {
        Image(systemName: "info.circle")
        Text("Customized Disclosure")
            .font(.headline)
            .foregroundColor(.white)
    }
    .padding()
    .background(Color.blue)
    .cornerRadius(10)
}
  • 外观定制:
    • 折叠内容部分添加背景色(Color.green.opacity(0.2))。
    • 标题部分是一个 HStack,其中有图标和文字,并带有蓝色背景。

4. 折叠动画 #

DisclosureGroup 内置了动画支持。当折叠或展开时,内容会自动使用淡入淡出的动画效果。如果需要更复杂的效果,也可以结合 .animation() 或自定义过渡。

示例: #

@State private var isExpanded = false

DisclosureGroup(isExpanded: $isExpanded) {
    VStack {
        Text("Expanded content with animation")
        Text("More details here...")
    }
    .padding()
    .background(Color.green.opacity(0.2))
    .cornerRadius(10)
} label: {
    Text("Tap to Animate")
        .font(.headline)
        .foregroundColor(.blue)
}
.animation(.linear, value: isExpanded) // 添加动画效果

5. DisclosureGroup 使用场景 #

以下是一些典型的使用场景:

  1. 表单或设置页: 用于分组 UI 内容,比如过滤器、表单分组、分类折叠等。

    struct SettingsView: View {
        var body: some View {
            DisclosureGroup("Settings") {
                Toggle("Enable Notifications", isOn: .constant(true))
                Toggle("Enable Dark Mode", isOn: .constant(false))
            }
            .padding()
            .background(Color.gray.opacity(0.2))
            .cornerRadius(10)
        }
    }
    
  2. 目录导航: 用于显示嵌套的文件夹目录或项目细分结构。

    struct FolderView: View {
        var body: some View {
            DisclosureGroup("Project A") {
                Text("File 1")
                Text("File 2")
            }
            DisclosureGroup("Project B") {
                Text("File 3")
                Text("File 4")
            }
        }
    }
    

6. 总结 #

特性描述
动态绑定通过 @StateBinding 绑定,可以灵活控制折叠状态。
易于嵌套支持嵌套多个 DisclosureGroup,适用于目录结构或多级设置。
自定义样式可通过修饰符(比如 foregroundColorbackground)定制标题和折叠内容的样式。
动画支持自动支持折叠和展开动画;结合 .animation() 可以实现更复杂的过渡效果。
场景表单分组、过滤器、目录导航、小工具折叠(如 FAQ 一问一答)等。

DisclosureGroup 是一个功能强大且灵活的组件,可以大幅简化折叠折叠组件的开发工作。

本文共 1465 字,上次修改于 Jan 12, 2025