Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI: Center Content in ScrollView

Tags:

swiftui

I'm trying to center a bunch of views in a VStack within a ScrollView in SwiftUI. To simplify things, I'm just trying to get it to work with a single Text view. Here's what I've come up with so far:

var body: some View {
  ScrollView(alwaysBounceVertical: true){
    HStack(alignment: .center) {
      Spacer()
      Text("This Is a Test")
      Spacer()
    } //HStack
    .background(Color.green)
  } //ScrollView
  .background(Color.gray)
}

This results in this:

enter image description here

I want the text to be in the middle like this:

enter image description here

So the HStack should be full-width and the Text should be centered within it. It seems like this should be easy, but I don't get what I'm doing wrong. :)

like image 390
Clifton Labrum Avatar asked Jun 15 '19 00:06

Clifton Labrum


3 Answers

Using GeometryReader, you can get information about the size of the containing view and use that to size your view.

    var body: some View {
        GeometryReader { geometry in                <--- Added
            ScrollView(alwaysBounceVertical: true){
                HStack(alignment: .center) {
                    Spacer()
                    Text("This Is a Test")
                    Spacer()
                } //HStack
                .frame(width: geometry.size.width)  <--- Added
                .background(Color.green)
            } //ScrollView
        .background(Color.gray)
    }
}

edit: after looking into this more, it seems that part of the problem is that you are using a ScrollView. If you remove that parent, the spacers in the HStack will automatically cause stretching to fill the view. I'm guessing the automatic stretching doesn't happen in ScrollViews because there's no finite limit to how big it can be, how much would it stretch? (because a ScrollView can scroll in any direction)

like image 115
Benjamin Kindle Avatar answered Nov 16 '22 00:11

Benjamin Kindle


You should use the modifier frame and set its maxWidth: .infinity. So it tells its parent: "the wider, the better" :)

var body: some View {
  ScrollView(.vertical, showsIndicators: true){
    HStack(alignment: .center) {
      Spacer()
      Text("This Is a Test")
        .frame(maxWidth: .infinity) // <- this
      Spacer()
    } //HStack
    .background(Color.green)
  } //ScrollView
  .background(Color.gray)
}

And this works regardless its parent. Scrollview or whatever View it's set in.

Paul is doing a great job clarifying it to all of us here:

https://www.hackingwithswift.com/quick-start/swiftui/how-to-give-a-view-a-custom-frame

Answer compatible with Xcode 12.1 (12A7403) I hope this helps 👍 dsa

like image 31
Danilo Avatar answered Nov 15 '22 22:11

Danilo


This seems to be a bug in Xcode 11.0 beta, ScrollView content wouldn't fill the scroll view. If you replace the ScrollView with a List it will work as expected. But if you have to use a scroll view, one workaround is to fix the scroll view's content width.

So your code will look something like this:

ScrollView(alwaysBounceVertical: true) {
  HStack(alignment: .center) {
    Spacer()
    Text("This Is a Test")
    Spacer()
  } // HStack
  .frame(width: UIScreen.main.bounds.width) // set a fixed width
  .background(Color.green)
} // ScrollView
.background(Color.gray)

Result:

enter image description here

like image 31
M Reza Avatar answered Nov 15 '22 22:11

M Reza