'SwiftUI - nested list
I'm trying to create a nested hierarchical list, so that for each task I can have subtasks like in iOS reminders app:
First attempt was to embed another list inside a list cell.
import SwiftUI
struct SwiftUIView: View {
var body: some View {
List {
List {
Text("Hello, World!")
}
}
}
}
struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
SwiftUIView()
}
But, didn't work out...
Anyone can help?
cheers
Solution 1:[1]
Why do you think it should be List in List... Such visual representation can be generated using only one list and it will have native look & feel.
Here is just a demo (w/o UI tuning and logic of showing/hiding sections, that is out of topic), but the idea should be clear
struct ItemRow: View {
let category: Bool
let text: String
init(_ text: String, isCategory: Bool = false) {
self.category = isCategory
self.text = text
}
var body: some View {
HStack {
Circle().stroke() // this can be custom control
.frame(width: 20, height: 20)
.onTapGesture {
// handle tap here
}
if category {
Text(self.text).bold()
} else {
Text(self.text)
}
}
}
}
struct TestNestedLists: View {
var body: some View {
List { // next pattern easily wrapped with ForEach
ItemRow("Category", isCategory: true) // this can be section's header
Section {
ItemRow("Item 1")
ItemRow("Item 2")
ItemRow("Item 3")
}.padding(.leading, 20)
}
}
}
Solution 2:[2]
It's not hard, but you have to manually add some frame.
struct SwiftUIViewList: View {
var body: some View {
List {
Text("Hello, World!")
Text("Hello, World!")
}
}
}
struct SwiftUIView: View {
var body: some View {
List {
Text("item1")
SwiftUIViewList().frame(height: 100)
Text("item3")
}
}
}
Solution 3:[3]
Place one list inside another, like this small example:
struct ContentView: View {
var body: some View {
List {
Text("External List")
List {
Text("Internal List")
}
}
}
}
It results in this: Result Error
I was testing and found that the error occurs when the style of the inner list is any grouped style (.grouped, .insetGrouped or the new .sidebar).
In contrast, if the internal list has any non-grouped style (.inset or .plain) it works correctly.
struct ContentView: View {
var body: some View {
List {
Text("External List")
List {
Text("Internal List")
}
.listStyle(.plain)
}
}
}
It results in this: Result OK
Beyond this, as mentioned in many places, you should not use nested lists. You should try to resolve with VStack or ForEach.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | E.Coms |
Solution 3 | GustavoLizio |