TL;DR: Prevent clipping in
ScrollView
by usingscrollClipDisabled(true)
on iOS 17+ or leveraging Introspect to setclipsToBounds = false
on older iOS versions.
Problem
In SwiftUI, ScrollView
clips content that exceeds its boundaries in the non-scrollable direction by default. How can we disable this behavior?
Solutions
1. Use scrollClipDisabled
(iOS 17+)
Starting with iOS 17, SwiftUI provides the scrollClipDisabled
modifier. Setting this to true
prevents ScrollView
from clipping content that extends beyond its boundaries.
struct ScrollClipDisableDemo: View {
@State private var disable = true
var body: some View {
VStack {
Toggle("Clip Disable", isOn: $disable)
.padding(20)
ScrollView {
ForEach(0 ..< 10) { i in
Rectangle()
.fill(.blue)
.frame(height: 100)
.shadow(color: .black, radius: 50)
.overlay(Text("\(i)").foregroundColor(.white))
}
}
}
.scrollClipDisabled(disable)
}
}
This will ensure that shadows, effects, or other content extending beyond the bounds of ScrollView
are visible.
2. Use Introspect for Older iOS Versions
Introspect is a third-party library that allows access to underlying UIKit objects. On older iOS versions, you can modify the clipsToBounds
property of the UIScrollView
to disable clipping.
import Introspect
struct ScrollClipDisableDemo: View {
@State private var disable = true
var body: some View {
VStack {
Toggle("Clip Disable", isOn: $disable)
.padding(20)
ScrollView {
ForEach(0 ..< 10) { i in
Rectangle()
.fill(.red)
.frame(height: 100)
.shadow(color: .black, radius: 50)
.overlay(Text("\(i)").foregroundColor(.white))
}
}
.introspect(.scrollView, on: .iOS(.v16, .v17, .v18)) { scrollView in
scrollView.clipsToBounds = !disable
}
}
.frame(width: 100)
}
}
This approach ensures compatibility with older versions of iOS where scrollClipDisabled
is not available.