Ultimately, I am trying to replicate the layout used in Apple's Tips app:
The app appears to have a NavigationStack that contains non-list items but that fit the overall list style. When I try to introduce a DisclosureGroup or GroupBox into the list, it has it's own padding for that item that I don't appear to be able to remove without removing it for all the lists breaking the layout achieved in the Tips app above.
If I introduce a ScrollView, then the List disappears and placing another item above the list makes only the List scrollable. This also stops the navigation bar from collapsing as you scroll.
Here's a simplified example of what I assumed would work:
NavigationStack {
GroupBox(label: Text("My Label"), content: {
Text("The content")
})
.padding()
List {
Section(header: Text("My First Section")) {
Text("First list item")
Text("Second list item")
}
}
.navigationTitle("Navigation Title")
.toolbarBackground(Color.blue)
}
In this example, the GroupBox appears tied to the NavigationStack title bar. If I give it a background colour, there's also a clear separation between the GroupBox and the List.
The Section headings are also non-standard but can be achieved with some simple modifiers but I am looking for a way to introduce non-list content into the scrollable view the List provides in SwiftUI.
I would happily place the GroupBox into a list if I could collapse the padding but that does not appear to work:
List {
Section {
GroupBox(label: Text("Label"), content: {
Text("Content")
})
.listRowInsets(.none)
.padding(0)
}
}
I am not particularly bothered by the search bar, although this may be a useful requirement for the future. Right now I would just like to build a view that made use of the NavigationStack which sets a title for the view and when you scroll the entire page scrolls. The design language here fits my use case perfectly but I've struggled with the insertion of non-list elements and hope someone can point me in the right direction.
When the GroupBox
is inside the List
, you can get rid of the extra padding by using explicit EdgeInsets
instead of .none
. Then to set a background color, use .backgroundStyle
:
NavigationStack {
List {
Section {
GroupBox("The Label") {
Text("The Content")
}
.backgroundStyle(.yellow)
}
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
Section(header: Text("My First Section")) {
Text("First list item")
Text("Second list item")
}
}
.navigationTitle("Navigation Title")
.toolbarBackground(Color.blue)
}
Alternatively, you can just use a VStack
and style it any way you like:
NavigationStack {
List {
Section {
VStack(alignment: .leading, spacing: 12) {
Text("The Label")
.font(.headline)
Text("The Content")
.frame(maxWidth: .infinity)
}
}
.listRowBackground(Color.orange)
Section(header: Text("My First Section")) {
Text("First list item")
Text("Second list item")
}
}
.navigationTitle("Navigation Title")
.toolbarBackground(Color.blue)
}