Search code examples
iosswiftuiviewswiftui

Problem with Clipshape and RoundedRectangle


I'm running into an issue where my ClipShape is disabled when a subview is bigger than the total screen width. I tried to patch it but i don't understand what's the problem here.

Here is two images and you'll found the code below :

Whit one card. Card width is equal to UIScreen.main.bounds.width With 3 cards.

Here's my complete code :

import SwiftUI

struct OnboardingView: View {

    @State var x: CGFloat = 0
    @State var count : CGFloat = 0
    @State var screen = UIScreen.main.bounds.width - 30
    @State var op : CGFloat = 0

    @State var data = [
        Card(id: 0, title: "Carte 1", image: "onboarding"),
        Card(id: 1, title: "Carte 2", image: "onboarding"),
        Card(id: 2, title: "Carte 3", image: "onboarding")
    ]

    var body: some View {

        ZStack(alignment: .top) {

            Color.black
                .edgesIgnoringSafeArea(.all)

            Color("background2")
            .edgesIgnoringSafeArea(.bottom)
            .clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous))


            HStack(spacing: 15) {

                ForEach(data) { i in
                    CardView(data: i)
                        .offset(x: self.x)
                    .highPriorityGesture(
                        DragGesture()
                            .onChanged { value in
                                if value.translation.width > 0 {
                                    self.x = value.location.x
                                } else {
                                    self.x = value.location.x - self.screen
                                }
                            }
                    )
                }
            }


//                CardView(data: data[0])

            }


        }
    }

struct OnboardingView_Previews: PreviewProvider {
    static var previews: some View {
        OnboardingView()
    }
}


struct CardView: View {

    @State var show = false
    var data: Card


    var body: some View {

        VStack {
            // Title - use the geometry reader to adapt font size.
            GeometryReader { geometry in
                Text(self.data.title)
                    .font(.system(size: geometry.size.width / 9, weight: .bold))
                    .foregroundColor(.white)

            }
            .frame(maxWidth: 375, maxHeight:  220)
            .padding(.horizontal, 16)

            Spacer()
        }
        .frame(width: UIScreen.main.bounds.width)
        .offset(x: show ? 0 : -500)
        .multilineTextAlignment(.center)
        .padding(.top, 25)
        .frame(height: 477)
        .background(
            ZStack {
                Image(uiImage: #imageLiteral(resourceName: "Blob"))
                    .offset(x: -150, y: -200)
                    .rotationEffect(Angle(degrees: show ? 360 + 90 : 90))
                    .blendMode(.plusDarker)
                    .animation(Animation.linear(duration: 120).repeatForever(autoreverses: false))
                    .onAppear {
                        self.show = true
                }

                .background(
                    Image(uiImage: #imageLiteral(resourceName: "Blob"))
                        .offset(x: -200, y: -250)
                        .rotationEffect(Angle(degrees: show ? 360 : 0), anchor: .leading)
                        .blendMode(.overlay)
                        .animation(Animation.linear(duration: 100).repeatForever(autoreverses: false))
                )
            }
        )
            .background(
                Image(self.data.image)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 300)
                    .opacity(0.8),
                alignment: .bottom
            )
            .background(Color("card1"))
            .clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous))
    }
}

struct Card: Identifiable {
    var id: Int
    var title: String
    var image: String
}

Can someone help please ? The RoundedRectangle Clipshape only disapear when i display all my cards. I think there's a problem because the total width of the HStack is larger than the background i applied the clipshape to.

How can i fix this ? Thanks a lot !


Solution

  • Here is a solution that gives desired clipping

    var body: some View {
        ZStack(alignment: .top) {
    
            Color.black
                .edgesIgnoringSafeArea(.all)
    
            Rectangle().fill(Color.gray)
                .edgesIgnoringSafeArea(.bottom)
                .clipShape(RoundedRectangle(cornerRadius: 30))
    
            Color.clear       // transparent clipped foreground window
                .background(
                    VStack {  // clipped background content
                        HStack(spacing: 15) {
                            ForEach(data) { i in
                                CardView(data: i)
                                    .offset(x: self.x)
                                    .highPriorityGesture(
                                        DragGesture()
                                            .onChanged { value in
                                                if value.translation.width > 0 {
                                                    self.x = value.location.x
                                                } else {
                                                    self.x = value.location.x - self.screen
                                                }
                                        }
                                )
                            }
                        }
                        Spacer()
                    }
                )
                .edgesIgnoringSafeArea(.bottom)
                .clipShape(RoundedRectangle(cornerRadius: 30))
        }
    }