Skip to content

Commit 0c9f988

Browse files
author
Trent Guillory
committed
Added configuration for header.
1 parent a1153a1 commit 0c9f988

File tree

4 files changed

+81
-25
lines changed

4 files changed

+81
-25
lines changed

ScrollViewReactiveHeaderDemoApp/Sources/ContentView.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ import SwiftUI
66
struct ContentView: View {
77

88
var body: some View {
9-
9+
1010
TabView {
1111

1212
StoryListView()
1313
.tabItem {
1414
VStack {
15-
Image(systemName: "book")
16-
.foregroundColor(.gray)
17-
Text("Reader")
18-
.foregroundColor(.gray)
15+
Image(systemName: "book")
16+
17+
Text("Reader")
1918
}
2019
}
2120
}
21+
.accentColor(.black)
2222
.preferredColorScheme(.light)
2323
}
2424
}

ScrollViewReactiveHeaderDemoApp/Sources/Example3/StoryListView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ struct StoryListView: View {
2121
}, body: {
2222

2323
StoryListContentView(viewModel: viewModel)
24-
})
24+
}, configuration: .init(showStatusBar: true))
2525
}
2626
}
2727

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Trent Guillory on 9/5/21.
6+
//
7+
8+
import Foundation
9+
10+
public struct ScrollViewConfiguration {
11+
12+
public init(showStatusBar: Bool) {
13+
14+
self.showStatusBar = showStatusBar
15+
}
16+
17+
let showStatusBar: Bool
18+
}

Sources/ScrollViewReactiveHeader.swift

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ public struct ScrollViewReactiveHeader<A, B, C>: View where A: View, B: View, C:
88
public init(
99
@ViewBuilder header: @escaping () -> A,
1010
@ViewBuilder headerOverlay: @escaping () -> B,
11-
@ViewBuilder body: @escaping () -> C) {
11+
@ViewBuilder body: @escaping () -> C,
12+
configuration: ScrollViewConfiguration) {
1213

1314
self.header = header
1415
self.headerOverlay = headerOverlay
1516
bodyContent = body
17+
self.configuration = configuration
1618
}
1719

1820
// MARK: Public
@@ -40,10 +42,21 @@ public struct ScrollViewReactiveHeader<A, B, C>: View where A: View, B: View, C:
4042
VStack(content: bodyContent)
4143
.background(backgroundColor)
4244
}
45+
46+
if configuration.showStatusBar {
47+
48+
Rectangle()
49+
.fill(Color.white)
50+
.opacity(statusBarOpacity)
51+
.frame(height: geometry.safeAreaInsets.top)
52+
.edgesIgnoringSafeArea(.top)
53+
.onAppear {
54+
55+
topSafeArea = geometry.safeAreaInsets.top
56+
}
57+
}
4358
}
4459
.onPreferenceChange(ScrollViewHeaderKey.self, perform: { preference in
45-
46-
print("~ header size: \(preference.rect.height)")
4760

4861
guard preference.rect != .zero,
4962
headerHeight == .none else { return }
@@ -54,24 +67,10 @@ public struct ScrollViewReactiveHeader<A, B, C>: View where A: View, B: View, C:
5467
.background(backgroundColor)
5568
.coordinateSpace(name: "ReactiveHeader")
5669
.onPreferenceChange(ScrollViewBodyKey.self, perform: { preference in
57-
58-
headerOffset = min(0, preference.rect.minY / 10)
59-
60-
headerScale = max(1, 1 + preference.rect.minY / 500)
6170

62-
print(preference.rect)
63-
64-
guard let headerHeight = headerHeight else { return }
65-
66-
let startingY = headerHeight / 2
71+
setStatusBarOpacity(offset: preference.rect.minY)
6772

68-
if abs(preference.rect.minY) > startingY {
69-
70-
headerOpacity = (1 - (abs(preference.rect.minY) - startingY) / startingY)
71-
} else {
72-
73-
headerOpacity = 1
74-
}
73+
setHeaderOpacity(preferenceRect: preference.rect)
7574
})
7675
}
7776

@@ -89,9 +88,48 @@ public struct ScrollViewReactiveHeader<A, B, C>: View where A: View, B: View, C:
8988
private var header: () -> A
9089
private var headerOverlay: () -> B
9190
private var bodyContent: () -> C
91+
private var configuration: ScrollViewConfiguration
9292

9393
@State private var headerHeight: CGFloat?
9494
@State private var headerOffset: CGFloat = .zero
9595
@State private var headerScale: CGFloat = 1
9696
@State private var headerOpacity: CGFloat = 1
97+
98+
@State private var statusBarOpacity: Double = 0
99+
@State private var topSafeArea: CGFloat = 40
100+
101+
private func setHeaderOpacity(preferenceRect: CGRect) {
102+
103+
headerOffset = min(0, preferenceRect.minY / 10)
104+
105+
headerScale = max(1, 1 + preferenceRect.minY / 500)
106+
107+
guard let headerHeight = headerHeight else { return }
108+
109+
let startingY = headerHeight / 2
110+
111+
if abs(preferenceRect.minY) > startingY {
112+
113+
headerOpacity = (1 - (abs(preferenceRect.minY) - startingY) / startingY)
114+
} else {
115+
116+
headerOpacity = 1
117+
}
118+
}
119+
120+
private func setStatusBarOpacity(offset: CGFloat) {
121+
122+
guard let headerOffset = headerHeight else { return }
123+
124+
let scrollOffset = offset + headerOffset
125+
126+
print(scrollOffset)
127+
128+
switch scrollOffset {
129+
130+
case 40 ... 60: statusBarOpacity = Double(-scrollOffset / 100.0)
131+
case ...(40): statusBarOpacity = 1
132+
default: statusBarOpacity = 0
133+
}
134+
}
97135
}

0 commit comments

Comments
 (0)