SwiftUI Scrollview disable clipping

See the following sample code:

Code Block swift
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 20) {
ForEach(0 ..< 12) { index in
Rectangle()
.foregroundColor(.white)
.frame(width: 100, height: 100, alignment: .center)
.shadow(radius: 20)
}
}
}


This sample code will result in a horizontal scrollview
with rectangles as elements.
However as it seems the ScrollView actually clips its content
so any shadow on the top and bottom will be clipped.

Is there any way to disable automatic clipping by the scrollview
or another way to achieve this?




Answered by espen in 620431022
You can add padding to the HStack like shown below. But if anyone else has a suggestion on how you can blead the shadow onto the other views without using padding, I would appreciate it 😀

Code Block Swift
ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 20) {
                    ForEach(0 ..< 12) { index in
                        Rectangle()
                            .foregroundColor(.white)
                            .frame(width: 100, height: 100, alignment: .center)
                            .shadow(radius: 20)
                    }
                }
                .padding(35)
            }
            .padding(-20)


Accepted Answer
You can add padding to the HStack like shown below. But if anyone else has a suggestion on how you can blead the shadow onto the other views without using padding, I would appreciate it 😀

Code Block Swift
ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 20) {
                    ForEach(0 ..< 12) { index in
                        Rectangle()
                            .foregroundColor(.white)
                            .frame(width: 100, height: 100, alignment: .center)
                            .shadow(radius: 20)
                    }
                }
                .padding(35)
            }
            .padding(-20)


LazyHStack instead of HStack solved the clipping problem.

You can disable clipping with help of Introspect for SwiftUI https://github.com/siteline/SwiftUI-Introspect

Using it you can get underlying UIKit objects. In your case simply add this to the ScrollView.

ScrollView(.horizontal, showsIndicators: false) {
    //.....
}
.introspectScrollView { view in
    view.clipsToBounds = false
}

Hey guys, I've found a decent solution for this problem.

BEFORE:

AFTER:

I've added 2 paddings to ScrollView and to content of ScrollView with the same amount of padding but one with NEGATIVE value like this:

struct ScrollViewClippingProblem: View {
    var body: some View {
        VStack {
            Text("Lorem Ipsum")
                .font(.title)

            ScrollView(.horizontal, showsIndicators: false) {
                HStack(alignment: .top) {
                    ForEach(0..<10, content: { item in
                        Text("\(item)")
                            .font(.title)
                            .padding()
                            .background(Circle().fill(.red))
                            .shadow(color: .blue, radius: 10, x: 15, y: 10)
                    })
                }
                .padding(.vertical, 40) // <- add padding here to make the space for the shadow
            }
            .padding(.vertical, -40) // <- add NEGATIVE padding here of the same value to shrink the space you created with the padding above

            Text("Lorem Ipsum")
                .font(.title)
        }
        .background(.ultraThinMaterial)
    }
}

I hope this helps! :)

Hey guys

By default, the scrollView is clipped and the shadow is obscured.

Going to the trouble of attaching padding to an element adds complexity to the layout. The way I'm handling this is going to be a much more maintainable code. Put the following code anywhere you want

import UIKit

extension UIScrollView {
  open override var clipsToBounds: Bool {
    get { false }
    set { }
  }
}

Controls UIKit's UIScrollView's clipsToBounds. This will then be reflected in the SwiftUI's ScrollView and the clip will no longer function.

Now there is no need to bother adding padding to the element. And the shadow will not be clipped!

I recommend this

for more infomation


https://github.com/ramen2020/ScrollView-clipsToBounds/tree/main

This is now supported natively with the scrollClipDisabled() modifier (documentation) on the ScrollView

SwiftUI Scrollview disable clipping
 
 
Q