I have some data that will be loaded from a server and in the mean time I want to show a shimmer placeholder view.
To achieve the shimmer effect, I've created the following:
struct ShimmerEffectBox: View {
@State private var startPoint: UnitPoint = .init(x: -1.8, y: -1.2)
@State private var endPoint: UnitPoint = .init(x: 0, y: -0.2)
private var gradientColors = [
Color(uiColor: .systemGray5),
Color(uiColor: .systemGray6),
Color(uiColor: .systemGray5)
]
var body: some View {
LinearGradient(colors: gradientColors,
startPoint: startPoint,
endPoint: endPoint)
.onAppear {
withAnimation(.easeInOut(duration: 2)
.repeatForever(autoreverses: false)) {
startPoint = .init(x: 1, y: 1)
endPoint = .init(x: 2.2, y: 2.2)
}
}
}
}
The shimmer works fine and nothing needs to be looked at here.
I then create a ScrollView
with some data and my placeholder views, however, for some reason the views are overlapping, this is my code:
struct ContentView: View {
var body: some View {
ScrollView {
Text("Title")
.font(.system(size: 20))
.bold()
ForEach(1...5, id: \.self) { _ in
placeholderView
}
}
}
private var placeholderView: some View {
GeometryReader { proxy in
VStack(alignment: .leading, spacing: 4) {
ShimmerEffectBox()
.frame(width: proxy.size.width / 2, height: 18)
.cornerRadius(4)
ShimmerEffectBox()
.frame(height: 16)
.cornerRadius(4)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.bottom, 24)
}
}
}
This gives me the following result:
I'm sure that I'm doing something wrong with the geometry reader, so I added the padding to the geometry reader
private var placeholderView: some View {
GeometryReader { proxy in
VStack(alignment: .leading, spacing: 4) {
ShimmerEffectBox()
.frame(width: proxy.size.width / 2, height: 18)
.cornerRadius(4)
ShimmerEffectBox()
.frame(height: 16)
.cornerRadius(4)
}
.frame(maxWidth: .infinity, alignment: .leading)
}
.padding(.bottom, 24)
}
This is better, however, the padding is definitely not 24.
My goal is:
- I want 4 placeholder views (this is achieved by the loop - no issues)
- each placeholder view should have 2 shimmer views. One shimmer view is full width and one is half (this also works - no issues)
- I want a padding of 24 between each shimmer view - this doesn't work
Not sure if I'm using geometry reader wrong or specifying the padding / spacing at the wrong place.