15

I have a list of buttons that display perfectly on iOS 13 using SwiftUI, but on iOS 14 it cuts the content off where the screen ends.

Has anything changed with regards to how HStacks renders what isn't on the screen? I used to scroll and be able to see all the buttons.

I will attach some screenshots and the code.

What initially loads into sight

When I scroll, the other buttons aren't visible and one is cut off

var body: some View {
        VStack(alignment: .leading, spacing: 0){
            Text("Select a venue type")
                .font(.custom("MavenProBold", size: 16))
                .padding(.leading, 16)
                .padding(.top, 18)
                .foregroundColor(Color.black)
            
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(alignment: .center, spacing: 4, content: {
                    
                    
                    Button(action: {
                        self.selectedButtonIndex = 0
                        
                    })
                    {
                        VStack(alignment: .center, spacing: 0, content: {
                            ZStack(alignment: .bottomTrailing){
                                
                                Image(systemName: "star.fill")
                                    .frame(width: circleFrameSize, height: circleFrameSize, alignment: .center)
                                    .font(.title)
                                    .background(Color(hexString: "#1A88FF"))
                                    .foregroundColor(Color.white)
                                    .clipShape(Circle())
                                
                            }
                            Text("Things to do")
                                    .padding(.top, 8)
                                    .font(.custom("MavenProBold", size: 12))
                                    .multilineTextAlignment(.center)
                                    .lineLimit(50)
                        })
                        .frame(width: 80, height: 80, alignment: .center)
                        .padding(.all, 10)
                        .foregroundColor(Color.black)
                        
                    }
                    
                    Button(action: {
                        self.selectedButtonIndex = 0
                        
                    })
                    {
                        VStack(alignment: .center, spacing: 0, content: {
                            ZStack(alignment: .bottomTrailing){
                                
                                Image(systemName: "star.fill")
                                    .frame(width: circleFrameSize, height: circleFrameSize, alignment: .center)
                                    .font(.title)
                                    .background(Color(hexString: "#1A88FF"))
                                    .foregroundColor(Color.white)
                                    .clipShape(Circle())
                                
                            }
                            Text("Things to do")
                                    .padding(.top, 8)
                                    .font(.custom("MavenProBold", size: 12))
                                    .multilineTextAlignment(.center)
                                    .lineLimit(50)
                        })
                        .frame(width: 80, height: 80, alignment: .center)
                        .padding(.all, 10)
                        .foregroundColor(Color.black)
                        
                    }

                    
                    Button(action: {
                        self.selectedButtonIndex = 0
                        
                    })
                    {
                        VStack(alignment: .center, spacing: 0, content: {
                            ZStack(alignment: .bottomTrailing){
                                
                                Image(systemName: "star.fill")
                                    .frame(width: circleFrameSize, height: circleFrameSize, alignment: .center)
                                    .font(.title)
                                    .background(Color(hexString: "#1A88FF"))
                                    .foregroundColor(Color.white)
                                    .clipShape(Circle())
                                
                            }
                            Text("Things to do")
                                    .padding(.top, 8)
                                    .font(.custom("MavenProBold", size: 12))
                                    .multilineTextAlignment(.center)
                                    .lineLimit(50)
                        })
                        .frame(width: 80, height: 80, alignment: .center)
                        .padding(.all, 10)
                        .foregroundColor(Color.black)
                        
                    }

                    
                    Button(action: {
                        self.selectedButtonIndex = 0
                        
                    })
                    {
                        VStack(alignment: .center, spacing: 0, content: {
                            ZStack(alignment: .bottomTrailing){
                                
                                Image(systemName: "star.fill")
                                    .frame(width: circleFrameSize, height: circleFrameSize, alignment: .center)
                                    .font(.title)
                                    .background(Color(hexString: "#1A88FF"))
                                    .foregroundColor(Color.white)
                                    .clipShape(Circle())
                                
                            }
                            Text("Things to do")
                                    .padding(.top, 8)
                                    .font(.custom("MavenProBold", size: 12))
                                    .multilineTextAlignment(.center)
                                    .lineLimit(50)
                        })
                        .frame(width: 80, height: 80, alignment: .center)
                        .padding(.all, 10)
                        .foregroundColor(Color.black)
                        
                    }

                    
                    Button(action: {
                        self.selectedButtonIndex = 0
                        
                    })
                    {
                        VStack(alignment: .center, spacing: 0, content: {
                            ZStack(alignment: .bottomTrailing){
                                
                                Image(systemName: "star.fill")
                                    .frame(width: circleFrameSize, height: circleFrameSize, alignment: .center)
                                    .font(.title)
                                    .background(Color(hexString: "#1A88FF"))
                                    .foregroundColor(Color.white)
                                    .clipShape(Circle())
                                
                            }
                            Text("Things to do")
                                    .padding(.top, 8)
                                    .font(.custom("MavenProBold", size: 12))
                                    .multilineTextAlignment(.center)
                                    .lineLimit(50)
                        })
                        .frame(width: 80, height: 80, alignment: .center)
                        .padding(.all, 10)
                        .foregroundColor(Color.black)
                        
                    }

                    
                    
                    
                    
                })
                    .padding(.leading, 8)
                    .padding(.trailing, 8)
                    .padding(.bottom, 8)
            }
        }
     
    }
joelgate
  • 235
  • 2
  • 8
  • Provided code snapshot (with replicated absent parts) works fine with Xcode 12.0 / iOS 14. So the issue probably in some other code. – Asperi Oct 08 '20 at 14:06
  • 1
    I will take another look elsewhere, thanks! I have since set the hstack and scrollview to have different background colours, and the hstack colour ends where the screen ends, and you can see the scrollview background colour. Oddly, the buttons in the hstack are still clickable and function properly, they just don't appear and the visibility, not functionality, of the hstack gives way to the scrollview. – joelgate Oct 08 '20 at 14:38
  • I also just noticed this behavior as well! I'm trying to figure it out now and find the common denominator in our code. Buttons work, but aren't visible when scrolling beyond the width of the phone. – Kyle Beard Oct 10 '20 at 02:45
  • I have found the issue, I was using clipShape on the ScrollView. I was using cornerRadius with the extension for specific corners produced by Mojtaba Hosseini on https://stackoverflow.com/questions/56760335/round-specific-corners-swiftui Perhaps you too are clipping a shape somewhere. It did used to work on iOS 13 mind, still don't know why. I have removed clipShape but now my UI isn't anywhere near what it should be unfortunately. – joelgate Oct 10 '20 at 08:36

1 Answers1

18

I also met this problem. It happens when you have a customized clipShape outside of ScrollView. By customized I mean customized Path of the shape.

From my test, when you use builtin shapes, it works fine, for example:

view.clipShape(Circle())

When you use customized shape but with builtin Path, it also works fine, for example:

view.clipShape(CustomShape())

// which CustomShape is something like:

struct CustomShape: Shape {
    func path(in rect: CGRect) -> Path {
        return Path(roundedRect: rect, cornerSize: CGSize(width: 10, height: 10)
    }
}

But when you use a customized Path in your CustomShape, this issue happens:

view.clipShape(CustomShape())

// which CustomShape is something like:

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

I also tried to draw the path manually(use move, addLine, addArc), it doesn't work.

So the workaround is to use builtin Path in your customized Shape. I guess this is a bug of iOS 14, because it works fine on iOS 13.

Kyle Xie
  • 385
  • 2
  • 12
  • Want to say, that the similar issue wasn't noticed in Xcode 12 (which supports iOS 14 too), but begins with my update to Xcode 12.1. And your workaround doesn't solve my problem – Accid Bright Oct 30 '20 at 08:41
  • Are you using clipShape or clipShae(Circle()) anywhere? – joelgate Oct 30 '20 at 14:05
  • Hi @AccidBright, sorry to hear that. I tested my code with Xcode 12.1 on iOS 14.1, in my situation, using something like `clipShae(Circle())` works fine. – Kyle Xie Nov 02 '20 at 01:58
  • Hi @joelgate, yeah, I used `clipShape` to create a rounded corner on the top left and top right of a view. – Kyle Xie Nov 02 '20 at 01:59
  • Thank you @KyleXie! this was driving me crazy. I was using .contentShape and .mask() modifier to round only the two top corners of a scrollable sheet, and I had no idea why the bottom gets clipped beyond a certain size. – Zoltán Lippai Feb 23 '21 at 20:44
  • This really saved my day. Thanks a ton. – Jagoan Neon Apr 14 '21 at 05:25
  • 1
    thx for finding problem, am also use the same custom rounded corner modifier... – Alex Kraev Jul 14 '22 at 10:29