How to create something like this
LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) {
Section(header: Text("foo") ) {
LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) {
Section (header: Text("bar") ) {
Text("1")
Text("2")
...
}
Section (header: Text("baz") ) {
Text("1")
Text("2")
...
}
}
}
}
I need two fixed header but in this solution headers colide when fixed position
Thanks
CodePudding user response:
You can give the sub headers a background (in white / bg color), and also have to push the first header back using zIndex
.
struct ContentView: View {
var body: some View {
ScrollView {
LazyVStack(alignment: .leading, pinnedViews: [.sectionHeaders]) {
Section(header:
Text("Overall Header")
.zIndex(-1) // zIndex here
) {
LazyVStack(alignment: .leading, pinnedViews: [.sectionHeaders]) {
Section (header:
Text("Header One")
// give background here
.frame(maxWidth: .infinity, alignment: .leading)
.background(.gray)
) {
ForEach(0..<30) { item in
Text("Item \(item)")
}
}
Section (header:
Text("Header Two")
// give background here
.frame(maxWidth: .infinity, alignment: .leading)
.background(.gray)
) {
ForEach(0..<50) { item in
Text("Item \(item)")
}
}
}
}
}
}
.font(.title2)
.padding()
}
}
CodePudding user response:
Here is some hack :)
It' using the package "SwiftUITrackableScrollView" to be found here:
"https://github.com/maxnatchanon/trackable-scroll-view".
But there are several solutions for a trackable scrollview you can find, or implement one by yourself.
It works fine, the only problem is to get/define the relevant positions of headers. Its easy if you have a predefined/fixed item height.
import SwiftUI
import SwiftUITrackableScrollView
struct MyHeaders: Identifiable {
let id = UUID()
let title: String
let position: CGFloat
var active: Bool = false
}
struct ContentView: View {
@State private var offset = CGFloat.zero // Content offset available to use
@State private var myHeaders = [
MyHeaders(title: "Outer Header One", position: 0),
MyHeaders(title: "Inner Header One", position: 0),
MyHeaders(title: "Inner Header Three", position: 264),
MyHeaders(title: "Outer Header Two", position: 525),
MyHeaders(title: "Inner Header Three", position: 525),
]
var body: some View {
TrackableScrollView(.vertical, showIndicators: false, contentOffset: $offset) {
LazyVStack(alignment: .leading) {
Text("Outer Header One")
Text("Inner Header One")
ForEach(0..<10) { item in
Text("Item \(item)")
}
Text("Inner Header Two")
ForEach(0..<10) { item in
Text("Item \(item)")
}
Text("Outer Header Two")
Text("Inner Header Three")
ForEach(0..<30) { item in
Text("Item \(item)")
}
}
}
.onChange(of: offset) { newValue in
print(offset)
for i in 0..<myHeaders.count {
myHeaders[i].active = myHeaders[i].position < offset
}
}
.overlay(
VStack(alignment: .leading) {
ForEach(myHeaders) { header in
if header.active {
Text(header.title)
}
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(.orange)
.background(.background)
, alignment: .topLeading
)
.font(.title2)
.padding()
}
}