How to round only top corners of a scrollview in swiftui in latest iOS 14

Viewed 2281

I am trying to round only the top corners of a scrollview. Providing a custom shape in .clipShape() modifier used to work fine in earlier iOS versions but in the latest iOS 14 the bottom content of scrollview is disappearing. Please do suggest any workarounds

Here's the custom shape for rounding specific corners:

struct RoundedCorner: Shape {
    
    var radius: CGFloat = .infinity
    var corners: UIRectCorner = .allCorners
    
    func path(in rect: CGRect) -> Path {
        let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        return Path(path.cgPath)
    }
}

extension View {
    func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {
        clipShape( RoundedCorner(radius: radius, corners: corners) )
    }
}

here's the code for a sample view implementing custom rounded corner modifier:

struct SampleView: View {
    
    @State var fullname: String
    @State var email: String
    @State var phone: String
    @State var username: String
    
    var body: some View {
        ZStack {
            Color(.red).edgesIgnoringSafeArea(.top)
            VStack {
                Header()
                ZStack {
                    Color(.systemBackground).edgesIgnoringSafeArea(.bottom)
                    ScrollView {
                        VStack {
                            Text("Title")
                                .font(.largeTitle)
                                .foregroundColor(.primary)
                                .bold()
                                .padding()
                                .frame(maxWidth: .infinity, alignment: .leading)
                            TextField("type here...", text: $fullname)
                                .padding()
                            TextField("type here...", text: $email)
                                .padding()
                            TextField("type here...", text: $phone)
                                .padding()
                            TextField("type here...", text: $username)
                                .padding()
                            TextField("type here...", text: $fullname)
                                .padding()
                            TextField("type here...", text: $email)
                                .padding()
                            TextField("type here...", text: $phone)
                                .padding()
                            TextField("type here...", text: $username)
                                .padding()
                            Button(action: {  }, label: {
                                Text("Submit")
                                    .padding()
                                    .textCase(/*@START_MENU_TOKEN@*/.uppercase/*@END_MENU_TOKEN@*/)
                            })
                            .padding()
                        }
                    }
                }
                .frame(height: UIScreen.screenHeight/1.5)
                .cornerRadius(10, corners: [.topLeft, .topRight])
            }
        }
    }
}

private struct Header: View {
    var body: some View {
        HStack(alignment: .top) {
            VStack(alignment: .leading) {
                Text("")
                    .foregroundColor(Globals.Color.background)
                Spacer()
            }
            Spacer()
        }
    }
}

Here's the screenshot with bottom content clipped off:

Sample scrollview with custom rounded corners

1 Answers

Instead of applying your .cornerRadius modifier to the ScrollView, apply it to the background:

ZStack {
  Color(.systemBackground).edgesIgnoringSafeArea(.bottom)
    .cornerRadius(10, corners: [.topLeft, .topRight])
  ScrollView {
  //...
Related