Skip to content

Instantly share code, notes, and snippets.

@DevonMartin
Created August 18, 2023 18:28
Show Gist options
  • Save DevonMartin/c638cce386eff34aab585fc1496e8bae to your computer and use it in GitHub Desktop.
Save DevonMartin/c638cce386eff34aab585fc1496e8bae to your computer and use it in GitHub Desktop.
Scrollable see-through view
struct ContentView: View {
@State private var scrollViewHeight: CGFloat = .zero
@State private var VStackHeight: CGFloat = .zero
@State private var numberOfMessages = 5
var body: some View {
NavigationStack {
ScrollView {
VStack(spacing: 0) {
ForEach(0..<numberOfMessages, id: \.self) { i in
ShapeView(isSeeThrough: i % 2 == 0)
}
}
.background {
putViewHeight(in: $VStackHeight)
}
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Stepper("# of msgs", value: $numberOfMessages)
}
}
.background {
Rectangle()
.frame(height: min(scrollViewHeight, VStackHeight))
.foregroundStyle(.purple.gradient)
.frame(maxHeight: .infinity, alignment: .top)
}
.background {
putViewHeight(in: $scrollViewHeight)
}
.padding(.horizontal, 14)
}
}
@ViewBuilder
private func putViewHeight(in height: Binding<CGFloat>) -> some View {
GeometryReader { proxy in
Color.clear
.onAppear {
height.wrappedValue = proxy.size.height
}
.onChange(of: proxy.size.height) {
height.wrappedValue = $0
}
}
}
}
struct ShapeView: View {
@State private var textWidth: CGFloat = .infinity
@State private var viewWidth: CGFloat = .infinity
let backgroundCoverColor = Color(.systemBackground)
let isSeeThrough: Bool
var body: some View {
VStack(spacing: 0) {
HStack(spacing: 0) {
// Leading Background Cover for opaque messages
if !isSeeThrough,
viewWidth != .infinity,
textWidth != .infinity {
backgroundCoverColor
.frame(width: viewWidth - textWidth)
}
Text("Styled Text In Custom Shape")
.foregroundColor(isSeeThrough ? Color(.systemBackground) : .primary)
.padding()
.background {
putViwWidth(in: $textWidth)
}
.background {
if !isSeeThrough {
Color.yellow
}
}
// Trailing Background Cover for semi-transparent messages
if isSeeThrough,
viewWidth != .infinity,
textWidth != .infinity {
backgroundCoverColor
.frame(width: viewWidth - textWidth)
}
}
// Bottom Background Cover
backgroundCoverColor
.frame(height: 5)
}
.background {
putViwWidth(in: $viewWidth)
}
}
@ViewBuilder
private func putViwWidth(in width: Binding<CGFloat>) -> some View {
GeometryReader { proxy in
Color.clear
.onAppear {
width.wrappedValue = proxy.size.width
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment