SwiftUI中如何自定义具备默认功能的DisclosureGroup(下拉组件)?
自定义SwiftUI DisclosureGroup组件,实现完全自定义需求
原生SwiftUI的DisclosureGroup存在功能局限:无法移除左侧默认的蓝色箭头指示器,且标题区域的样式自定义空间有限(比如不能自由修改文字颜色、用图片替代文本)。下面实现一个完全自定义的CustomDisclosureGroup,既保留原生组件的展开/收起核心功能,又支持完全自定义的标题区域和内容区域,还能添加额外的点击回调逻辑。
自定义组件实现代码
import SwiftUI struct CustomDisclosureGroup<Prompt: View, Content: View>: View { @Binding var isExpanded: Bool let actionOnClick: () -> Void let prompt: Prompt let expandedView: Content var body: some View { VStack(alignment: .leading, spacing: 0) { Button(action: actionOnClick) { prompt .frame(maxWidth: .infinity, alignment: .leading) } if isExpanded { expandedView .transition(.opacity.combined(with: .slide)) } } } } // 可选:添加简化初始化器,支持直接传入标题文本 extension CustomDisclosureGroup where Prompt == Text { init(isExpanded: Binding<Bool>, actionOnClick: @escaping () -> Void, title: String, expandedView: Content) { self.isExpanded = isExpanded self.actionOnClick = actionOnClick self.prompt = Text(title) self.expandedView = expandedView } }
使用示例
按照你期望的方式使用自定义组件,完全自由定制标题区域和展开内容:
struct ContentView: View { @State private var isExpanded = false var body: some View { CustomDisclosureGroup(isExpanded: $isExpanded, actionOnClick: { isExpanded.toggle() print("执行额外逻辑") }, prompt: { HStack { Text("自定义标题行") .foregroundColor(.white) Spacer() Image("customArrow") .resizable() .frame(width: 12, height: 12) // 可选:根据展开状态旋转箭头 .rotationEffect(.degrees(isExpanded ? 90 : 0)) } .background(Color.blue) .padding() }, expandedView: { VStack { Text("自定义展开内容") Text("第二行内容") } .background(Color.red) .padding() }) .padding() } }
组件特性说明
- 完全自定义标题区域(
prompt参数):支持任意View组合,可修改文字颜色、添加图片、自定义背景等 - 完全自定义展开内容区域(
expandedView参数):自由放置任意视图 - 支持点击回调(
actionOnClick参数):除了展开/收起,可执行额外业务逻辑 - 保留核心的展开/收起状态绑定(
isExpandedBinding):方便外部控制状态
内容的提问来源于stack exchange,提问作者Anas Alhalabi
相关产品推荐
相关产品推荐

