Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to fit ScrollView to content in SwiftUI #769

Open
onmyway133 opened this issue Feb 6, 2021 · 5 comments
Open

How to fit ScrollView to content in SwiftUI #769

onmyway133 opened this issue Feb 6, 2021 · 5 comments

Comments

@onmyway133
Copy link
Owner

If we place ScrollView inside HStack or VStack, it takes all remaining space. To fit ScrollView to its content, we need to get its content size and constrain ScrollView size.

Use a GeometryReader as Scrollview content background, and get the local frame

import SwiftUI

struct HSearchBar: View {
    @State
    private var scrollViewContentSize: CGSize = .zero

    var body: some View {
        HStack {
            searchButton
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 12) {
                    ForEach(store.collections) { collection in
                        collectionCell(collection)
                    }
                }
                .background(
                    GeometryReader { geo -> Color in
                        DispatchQueue.main.async {
                            scrollViewContentSize = geo.size
                        }
                        return Color.clear
                    }
                )
            }
            .frame(
                maxWidth: scrollViewContentSize.width
            )
        }
    }
}
@hiteshsuthar1410
Copy link

Thnaks alot

@dhidalgofadrique
Copy link

Thanks a lot for this solution. Just one question: Why is it necessary to use DispatchQueue.main.async to set the scrollViewContentSize value? Is this assingment done in background? I do not understand the need of that dispatch

@stormychel
Copy link

Thanks a lot for this solution. Just one question: Why is it necessary to use DispatchQueue.main.async to set the scrollViewContentSize value? Is this assingment done in background? I do not understand the need of that dispatch

Leaving it out causes runtime warning: "Modifying state during view update, this will cause undefined behavior."

I am not exactly sure why because I agreed with you until trying this, will figure this out if I got some spare time on my hands...

@aehlke
Copy link

aehlke commented Sep 6, 2023

            .background(
                GeometryReader { geo in
                    Color.clear
                        .onAppear {
                            Task { @MainActor in
                                scrollViewContentSize = geo.size
                            }
                        }
                }
            )

something like this is a bit cleaner

@ryujim
Copy link

ryujim commented Feb 11, 2024

          .background(
              GeometryReader { geo in
                  Color.clear.task { scrollViewContentSize = geo.size }
              }
          )

Maybe maybe maybe...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants