james
james

Reputation: 889

SwiftUI center items in LazyVGrid

I am new to SwiftUI and am trying to center elements inside the LazyVGrid View.

Here is what I have currently:

enter image description here

Using:

var body: some View {
    ZStack {
        Color(red: 75/255, green: 0, blue: 130/255).ignoresSafeArea()
        VStack {
            LazyVGrid(columns: [GridItem(.adaptive(minimum: 30))], alignment: .center, spacing: 10) {
                let letters = wordToArray(word: testWord)
                ForEach(Array(letters.enumerated()), id: \.offset) { letter in
                    Text(String(letter.element).capitalized)
                        .foregroundColor(.blue)
                        .frame(width:30, height: 40)
                        .background(Color.yellow)
                        .cornerRadius(5)
                }
            }
            .padding()
        }
    }
}

But as you can see, this only aligns the elements to the left - I also do not know the number of characters that I may need to display. I would also like the keep the spacing between them the same as above.

Any help would be greatly appreciated!

Thanks.

Upvotes: 7

Views: 6799

Answers (3)

Jakir Hossain
Jakir Hossain

Reputation: 1072

Those who are still looking for answer like me, I have achieved solution in adaptive grid like this:

import SwiftUI

struct ContentView: View {
    
    private let adaptiveColumn = [
        GridItem(.adaptive(minimum: 250, maximum: 350))
    ]
    var body: some View {
        
        LazyVGrid(columns: adaptiveColumn, spacing: 20) {
            
            ForEach(1..<5) { item in
                Text(String(item))
                    .frame(width: 250, height: 50)
                    .padding(20)
                    .foregroundColor(.white)
                    .background(.blue)
                    .cornerRadius(10)
            }
        }
    }
}

#Preview {
    ContentView()
}

enter image description here The catch is you have to set minimum width so that another item does not able to fit in the right. If there is enough space for another item in the right, LazyVGrid will reserve that space for new item.

Upvotes: 0

belal medhat
belal medhat

Reputation: 524

I faced the same issue and couldn't solve it so I used a ScrollView and foreach to achieve the same way I need it

struct Subview: View {
var Items = ["a","b","c","d","e"]
var body: some View {
    ZStack(){
        Color("AccentColor").edgesIgnoringSafeArea(.all)
        VStack{
            HStack(alignment:.center){
            GeometryReader { geo in
                ScrollView(.horizontal,showsIndicators: false){
                HStack(alignment:.center){
                ForEach(Items, id: \.self) { item in
                Button {
                    } label: {
                Text("\(item)")
                }.frame(width:50,height: 50, alignment: .center).background(Color.red).cornerRadius(25)
                                
                }
                            
                            
                }.frame(width:geo.size.width,height: geo.size.height ,alignment: .center)
                        }
                    }
            }.frame(width: UIScreen.main.bounds.width - 40, height: 100, alignment: .center)
        }
        
    }.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height, alignment: .center)
            
}    }

enter image description here

Upvotes: 2

lorem ipsum
lorem ipsum

Reputation: 29291

2 options

struct CenteredLVSView: View {
    @State var letters: [String] = ["A", "B", "C", "D", "E","A", "B", "C", "D", "E","A", "B", "C", "D", "E"]
    //Specify column count and it will justify/center by width
    @State var columnCount: Int = 5
    var body: some View {
        ZStack {
            Color(red: 75/255, green: 0, blue: 130/255).ignoresSafeArea()
            LazyVGrid(columns: Array(repeating: GridItem(.flexible(minimum: 30
                 //If you set max it will center on width if smaller than max, uncomment below
                 //, maximum: 40
            )), count: columnCount), spacing: 10){
                ForEach(Array(letters.enumerated()), id: \.offset) { letter in
                    Text(String(letter.element).capitalized)
                        .foregroundColor(.blue)
                        .frame(width:30, height: 40)
                        .background(Color.yellow)
                        .cornerRadius(5)
                }
            }
            .padding()
        }
    }
}

LazyVGrid - Justified

Change to LazyHGrid

struct CenteredLVSView: View {
    @State var letters: [String] = ["A", "B", "C", "D", "E","A", "B", "C", "D", "E","A", "B", "C", "D", "E"]
    //Specify row count and it will justify/center height
    @State var rowCount: Int = 5
    var body: some View {
        ZStack {
            Color(red: 75/255, green: 0, blue: 130/255).ignoresSafeArea()
            LazyHGrid(rows: Array(repeating: GridItem(.flexible(minimum: 30
                //If you set max it will center if smaller than max, height uncomment below
                //, maximum: 40
            )), count: rowCount), spacing: 10){
                ForEach(Array(letters.enumerated()), id: \.offset) { letter in
                    Text(String(letter.element).capitalized)
                        .foregroundColor(.blue)
                        .frame(width:30, height: 40)
                        .background(Color.yellow)
                        .cornerRadius(5)
                }
            }
            .padding()
        }
    }
}

LazyHGrid - Justified

And as mentioned in the comments if you set a maximum they will be centered/justified to that max

LazyHGrid w/ 3 rows with a maximum of 40 LazyHGrid w/ 3 rows

LazyVGrid w/ 5 columns with a maximum of 40 LazyVGrid w/ 5 columns

Upvotes: 5

Related Questions