很多时候我们需要对视图合并起来处理样式,SwiftUI里提供了几种Group,为了很好的区别他们的关系,我整理了带Group单词的放到一起来说。方便记忆与区分。
如果您需要多个视图作为一个视图(例如,一起过渡),则应使用SwiftUI的Group视图。这一点特别重要,因为出于根本的技术原因,一次最多只能将10个视图添加到父视图。
超过10个视图,编译器就会开始报错了Extra argument in call:
VStack {
Text("第一行")
Text("第二行")
Text("第三行")
Text("第四行")
Text("第五行")
Text("第六行")
Text("第七行")
Text("第八行")
Text("第九行")
Text("第十行")
Text("第十一行")//报错:Extra argument in call
}
这是因为SwiftUI的视图构建系统具有各种代码,旨在让我们添加1个视图,2个视图,3个视图或4、5、6、7、8、9和10个视图,但不能添加11个或更多视图。
这时候Group就派上用场了:
VStack {
Group {
Text("第一行")
Text("第二行")
Text("第三行")
Text("第四行")
Text("第五行")
}
.font(.title)//批量设置Text的字号
Group {
Text("第六行")
Text("第七行")
Text("第八行")
Text("第九行")
Text("第十行")
Text("第十一行")
}.foregroundColor(.blue)//设置Group的颜色
}
这样编辑器就不会再报错了,我们可以超出10个视图的限制,因为VStack现在只能包含两个视图(两个Group组)。
Group与 Section(分组) 都有分组功能,他们也是有一些区别的,Group可以做为一个空视图返回给一个View,而Section主要用于List与From,自动设置一些样式,所以可以根据情况选择不同的分组。
是一个带有可选标签的程式化视图,该标签与内容的逻辑分组相关联。GroupBox 由两部分组成:可选的标签部分和主题的内容部分。
GroupBox(label: Label("完成事项",systemImage: "checkmark.circle.fill")) {
Text("跑步10仅是~ok")
Text("看书2小时~ok")
Text("调戏女同事被开除~ok")
}
其label是可选项,不设置则不会显示。GroupBox在不设置label的情况下与Group的差别就是它自带了显示的样式。
SwiftUI会自动为GroupBox设置边框与背景等,如果需要自己定义这些需要我们就需要使用到 .groupBoxStyle()。自己定义的样式需要符合protocol 协议 GroupBoxStyle。
//定义一个符合GroupBoxStyle协议的结构体用于用户按下时的样式设置
struct customStyle: GroupBoxStyle {
func makeBody(configuration: Configuration) -> some View {
//返回VStack与自己定义的样式
VStack(alignment: .leading) {
configuration.label //设置标题样式
.font(.title)
configuration.content//设置内容样式
.foregroundColor(.blue)
}
.padding()
.background(Color.red)
.clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous))
}
}
然后在GroupBox的后面加上参数:
.groupBoxStyle(customStyle())
即可完成了一个自定义的GroupBox样式。灵活性还是很不错的。
SwiftUI具有专用DisclosureGroup视图来呈现公开指示器并在其中包含内容。这可以绑定到某种布尔型属性,该布尔型属性确定内容当前是否可见,可以在其中放置许多视图以在展开时显示。
DisclosureGroup根据显示控件的状态(isExpanded)显示或隐藏另一个内容视图的视图。可用来分组显示内容,并可以通过 isExpanded 参数来控制内容默认是展开的还是折叠起来的,默认是折叠起来的。
例如,下面代码将创建一个DisclosureGroup内部包含大量文本的,默认情况下该文本将被隐藏的,需要用户将需要打开显示它:
struct ContentView: View {
@State private var revealDetails = false
var body: some View {
DisclosureGroup("显示介绍", isExpanded: $revealDetails) {
Text("这可能是一个很长的文本介绍内容,我在这里之所以没有写这么长,是因为我打字太累了,真的不想写这么多,我写了这么多废话你都还在看,你说你也够无聊的,看了这么多无聊的内容你为啥不给我点个赞,收藏、转发之类的。。。")
}
.frame(width: 300)
}
}
当然我们可以实现一个联动的开关(这是官方代码翻译后的样子):
struct ContentView: View {
struct ToggleStates {
var oneIsOn: Bool = true //第一个初始状态
var twoIsOn: Bool = false//第二个状态
}
@State private var toggleStates = ToggleStates()
@State private var topExpanded: Bool = true
var body: some View {
DisclosureGroup("项目展示", isExpanded: $topExpanded) {
Toggle("切换项目1", isOn: $toggleStates.oneIsOn)
Toggle("详情的开关", isOn: $toggleStates.twoIsOn)
DisclosureGroup("下面是详情哦~" , isExpanded: $toggleStates.twoIsOn) {
Text("没有详细")
}
}
}
}
OutlineGroup是一种类似于树的结构,根据需要从树状结构的识别数据的基础集合中计算视图和公开组。是用来显示树形结构的数据的空间。在下面例子中,我们的数据类型是描述的文件,有文件和文件夹的区别OutlineGroup 会自动遍历文件夹的所有子文件,从而绘制出嵌套的树形 UI。
1、先定义一个数据结构,用于目录信息:
//符合哈希、ID、自定义字符串转换协议
struct FileItem: Hashable, Identifiable, CustomStringConvertible {
var id: Self { self }//Identifiable协议
var name: String
var children: [FileItem]? = nil
var description: String {
switch children {
case nil:
return "文件:(name)"
case .some(let children):
return children.isEmpty ? "目录:(name)" : "目录:(name)"
}
}
}
然后准备我们要使用OutlineGroup展示的一组数据:
let data =FileItem(name: "主目录", children:
[FileItem(name: "用户文件夹", children:
[FileItem(name: "照片文件夹", children:
[FileItem(name: "照片.jpg"),
FileItem(name: "照片2.jpg")]),
FileItem(name: "电视文件夹", children:
[FileItem(name: "视频.mp4")]),
FileItem(name: "文档", children: [])
]),
FileItem(name: "新文件夹", children:
[FileItem(name: "子文档夹", children: [])
])
])
最后使用 OutlineGroup 展示上面的数据。即是一个可展开的偏历所有目录与文件夹:
OutlineGroup(data, children: .children) { item in
Text("(item.description)")
}
注意,OutlineGroup 和 DisclosureGroup 的区别:OutlineGroup是传入的数据为树形接口,自动生成 UI,而DisclosureGroup 则是我们设计的树形 UI。
除非注明,网络人的文章均为原创,转载请以链接形式标明本文地址:https://www.55mx.com/post/121
《【SwiftUI基础篇】7 几种分组显示Group、GroupBox、DisclosureGroup、OutlineGroup》的网友评论(0)