I am wanting to display three items across a screen equally. I am trying to make them all centered while having a leading alignment so when there is less than three they still maintain the same look. Im not very familiar with Lazy stack so I'm sure this is where my issue is coming into play. Currently if I have over three items the layout is correct, anything less than that the items do not have a leading alignment.
ScrollView {
LazyHStack(alignment: .center) {
LazyVStack(alignment: .leading, spacing: 10) {
ForEach(books.chunked(into: 3), id: \.self) { chunk in
LazyHStack(spacing: 30) {
ForEach(chunk, id: \.self) { book in
NavigationLink {
QuoteList(book: book)
} label: {
BookView(book: book)
.tint(.black)
}
.contextMenu {
Button("Delete") {
if let index = books.firstIndex(where: { $0.id == book.id}) {
modelContext.delete(books[index])
deleteBookTipDone.invalidate(reason: .actionPerformed)
}
}
}
}
}
}
.padding(.horizontal)
}
.padding(.bottom)
}
}
You can simply use .frame(maxWidth: .infinity)
on your LazyVStack
.
But here is another solution you might want to implement, using LazyGrids
First, I created some mock data just to show how it works, but you will use your own real data.
let books = [1,2,3,4,5] // This will be your array of Books
let columns = Array(repeating: GridItem(.flexible(), spacing: 15, alignment: .leading), count: 3)
Notice that I created the columns for the grid using a repeating array.
Next, I created a BookView
. In this case just a rectangle with some text.
struct BookView: View {
var body: some View {
VStack(alignment: .leading, spacing: 0) {
RoundedRectangle(cornerRadius: 12)
.fill(Color.brown)
.frame(height: 150)
Text("Book name")
.font(.body)
.fontWeight(.medium)
.foregroundStyle(Color.black)
.padding(.top, 10)
Text("Author")
.font(.subheadline)
.foregroundStyle(Color.gray)
}
.frame(maxWidth: .infinity)
}
}
Lastly, the grid itself. We use forEach to loop through all the books show them as a NavigationLink
so you link to the QuoteList
screen. I also added some horizontal padding just for looks...
LazyVGrid(columns: columns, spacing: 15) {
ForEach(books, id: \.self) { book in
NavigationLink {
// QuoteList(book: book)
} label: {
BookView()
}
.contextMenu {
Button("Delete") {
// Code
}
}
}
}
.padding(.horizontal, 15)
Now, if you want to add your top section you can do something like the following. This is the entire code all put together:
struct ContentView: View {
var body: some View {
let books = [1,2,3,4,5] // This will be your array of Books
let columns = Array(repeating: GridItem(.flexible(), spacing: 15, alignment: .leading), count: 3)
NavigationStack {
ScrollView {
VStack(spacing: 30) {
// This is the top section
ScrollView(.horizontal) {
HStack(spacing: 20) {
ForEach(0..<5) { _ in
RoundedRectangle(cornerRadius: 12)
.fill(Color.gray)
.frame(width: 200, height: 150)
}
}
.padding(.leading, 15)
}
.padding(.top, 30)
// This is the Books section
LazyVGrid(columns: columns, spacing: 15) {
ForEach(books, id: \.self) { book in
NavigationLink {
// QuoteList(book: book)
} label: {
BookView()
}
.contextMenu {
Button("Delete") {
// Code
}
}
}
}
.padding(.horizontal, 15)
}
.navigationTitle("Library")
}
}
}
}
struct BookView: View {
var body: some View {
VStack(alignment: .leading, spacing: 0) {
RoundedRectangle(cornerRadius: 12)
.fill(Color.brown)
.frame(height: 150)
Text("Book name")
.font(.body)
.fontWeight(.medium)
.foregroundStyle(Color.black)
.padding(.top, 10)
Text("Author")
.font(.subheadline)
.foregroundStyle(Color.gray)
}
.frame(maxWidth: .infinity)
}
}