watchOS 10+ 无DisclosureGroup时如何实现可折叠列表分区?
watchOS 10+ 无DisclosureGroup时如何实现可折叠列表分区?
太懂这种无奈了!watchOS 10+居然没给我们提供DisclosureGroup,想用iOS那套直接实现可折叠分区根本行不通——不过别慌,咱们自己搭一个完全能达到同样的效果,而且动画丝滑,体验和原生看齐!
核心思路
其实原理很简单:用一个绑定的布尔值控制分区的展开/收起状态,把分区头部改成可点击的按钮,再给内容加上过渡动画就搞定了。
基础实现代码
先从单个可折叠分区开始,代码一目了然:
import SwiftUI struct CollapsibleSectionView: View { // 控制分区展开状态的变量 @State private var isSectionExpanded = false var body: some View { List { Section { // 只有展开状态下才渲染内容 if isSectionExpanded { ForEach(0..<5) { index in Text("列表项 \(index + 1)") } // 给内容加上过渡动画,让展开收起更自然 .transition(.opacity.combined(with: .move(edge: .top))) } } header: { // 把头部做成可点击的按钮 Button(action: { // 包裹在withAnimation里,让状态切换带动画 withAnimation(.easeInOut(duration: 0.2)) { isSectionExpanded.toggle() } }) { HStack { Text("My Header") .font(.headline) Spacer() // 根据状态切换 Chevron 图标 Image(systemName: isSectionExpanded ? "chevron.down" : "chevron.right") .font(.caption) } .foregroundColor(.primary) } // 用PlainButtonStyle去掉按钮默认的高亮样式,更接近原生分区头 .buttonStyle(PlainButtonStyle()) } } } }
多分区场景优化
如果你的列表有多个可折叠分区,单独管理每个状态变量会很麻烦,建议把分区数据封装成模型:
// 定义分区模型,管理每个分区的标题、展开状态和子项 struct SectionModel: Identifiable { let id = UUID() let title: String var isExpanded: Bool let items: [String] } struct MultiCollapsibleSectionsView: View { @State private var sections: [SectionModel] = [ SectionModel(title: "我的收藏", isExpanded: false, items: ["照片", "音乐", "视频"]), SectionModel(title: "最近使用", isExpanded: true, items: ["文档A", "笔记B", "链接C"]) ] var body: some View { List { ForEach($sections) { $section in Section { if section.isExpanded { ForEach(section.items, id: \.self) { item in Text(item) } .transition(.opacity.combined(with: .move(edge: .top))) } } header: { Button(action: { withAnimation { section.isExpanded.toggle() } }) { HStack { Text(section.title) .font(.headline) Spacer() Image(systemName: section.isExpanded ? "chevron.down" : "chevron.right") } .foregroundColor(.primary) } .buttonStyle(PlainButtonStyle()) } } } } }
小技巧
- 动画时长可以根据自己的需求调整,
0.2-0.3秒左右的时长在watchOS上会很舒服 - 如果想让过渡效果更丰富,可以试试其他
Transition类型,比如scale或者slide - 按钮的样式可以根据你的App设计自定义,比如调整字体、颜色或者间距,完全适配你的UI风格
这样实现出来的效果和iOS上的DisclosureGroup几乎一模一样,点击头部就能切换状态,动画流畅,完全适配watchOS 10+的环境!
内容来源于stack exchange




