DRN
DRN

Reputation: 155

Scrollable content not working as expected in SwiftUI

I'm trying to create a scroll view with my custom view, but when I add scroll to view it's not working as expected, without scroll view working fine.

    struct ContentView: View {
        var body: some View {
            ScrollView(.vertical) {
                VStack {
                    ForEach (0..<2) { _ in
                        ListItem()
                    }
                }
            }
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }


 // But the below code is working fine.
 
    struct ContentView: View {
        var body: some View {
            VStack {
                ForEach (0..<2) { _ in
                    ListItem()
                }
            }
        }
    }

// List Item

struct ListItem: View {
    var body: some View {
        VStack {
            HStack {
                Image("steve")
                    .resizable()
                    .clipShape(Circle())
                    .aspectRatio(contentMode: .fit)
                    .frame(maxWidth:44, maxHeight: 44)
                VStack {
                    Text("Steve Jobs")
                        .font(.headline)
                        .frame(maxWidth: .infinity, alignment: .leading)

                    Text("1 hour ago")
                        .font(.footnote)
                        .frame(maxWidth: .infinity, alignment: .leading)
                }
                Spacer()

            }

            ZStack(alignment:.top) {
                GeometryReader { geometry in
                    VStack {

                        ZStack {
                            Image("poster_1")
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                                .cornerRadius(8)
                                .shadow(color: Color.black.opacity(0.12),
                                        radius: 4, x: 1, y: 1)
                                .frame(width: geometry.size.width - 64,
                                       height: geometry.size.height * 0.35)
                                .padding([.horizontal], 32)
                                .clipped()

                            ZStack {
                                Rectangle()
                                    .fill(Color.black.opacity(0.75))
                                    .frame(maxWidth:84 , maxHeight: 84)
                                    .cornerRadius(12)
                                Image(systemName: "play.fill")
                                    .font(.system(size: 44, weight: .bold))
                                    .foregroundColor(.white)

                            }

                        }

                        VStack {
                            Text("Game of Thrones")
                                .accentColor(Color.gray.opacity(0.25))
                                .font(Font.subheadline.weight(.bold))
                                .padding([.horizontal], 32)
                                .padding([.bottom], 2)

                                .frame(maxWidth: .infinity,
                                       alignment: .leading)

                            VStack {
                                Text("Game of Thrones is an American fantasy drama television series created by David Benioff and D. B. Weiss for HBO. ")
                                    .accentColor(Color.gray.opacity(0.25))
                                    .font(.footnote)
                                    .frame(maxWidth: .infinity,
                                           alignment: .leading)
                                    .padding([.horizontal], 32)
                                Text("Show more...")
                                    .accentColor(Color.gray.opacity(0.01))
                                    .font(Font.footnote.weight(.bold))
                                    .frame(maxWidth: .infinity,
                                           alignment: .trailing)
                                    .padding([.trailing], 32).onTapGesture {
                                        print("okay")
                                    }
                            }
                        }
                    }
                }
            }

        }
    }
}

ListItem contains multiple views which creates publisher info and movie information as shown below image.

Scrollview is scrolling but images are not shown in view as first image.

Here is the screenshot of both images

Upvotes: 2

Views: 7174

Answers (1)

Yrb
Yrb

Reputation: 9755

It is the geometry reader that you have in ListItem. Because neither a GeometryReader nor a Scrollview have their own size. Since neither know what size to render, they collapse. This is what you are seeing in your view. See this answer. The solution is to put the GeometryReader into ContentView outside the Scrollview and send the GeometryProxy that you called geometry into ListItem something like this:

struct ContentView: View {
        var body: some View {
            GeometryReader { geometry in
                ScrollView(.vertical) {
                    VStack {
                        ForEach (0..<2) { _ in
                            ListItem(geometry: geometry)
                        }
                    }
                } // Scrollview
            } // GeometryReader
        }
    }

struct ListItem: View {
    let geometry: GeometryProxy
    
    var body: some View {
        ...
    }

This seems to fix it in Preview, though you may have to change your multipliers in the .frame() that uses geometry to size it how you want.

Upvotes: 3

Related Questions