1

I'm trying to replicate this UI in SwiftUI using a Grid.

enter image description here

I created the cell like this.

struct MenuButton: View {
    let title: String
    let icon: Image
    
    var body: some View {
        Button(action: {
            print(#function)
        }) {
            VStack {
                icon
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 60, height: 60)
                Text(title)
                    .foregroundColor(.black)
                    .font(.system(size: 20, weight: .bold))
                    .multilineTextAlignment(.center)
                    .padding(.top, 10)
            }
        }
        .frame(width: 160, height: 160)
        .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.fr_primary, lineWidth: 0.6))
    }
}

And the Grid like so.

struct LoginUserTypeView: View {
    private let columns = [
        GridItem(.flexible(), spacing: 20),
        GridItem(.flexible(), spacing: 20)
    ]
    
    var body: some View {
        ScrollView {
            LazyVGrid(columns: columns, spacing: 30) {
                ForEach(Menu.UserType.allCases, id: \.self) { item in
                    MenuButton(title: item.description, icon: Image(item.icon))
                }
            }
            
            .padding(.horizontal)
            .padding()
        }
    }
}

But on smaller screens like the iPod, the cells are overlapped.

enter image description here

On bigger iPhone screens, still the spacing is not correct.

enter image description here

What adjustments do I have to make so that in every screen size, the cells would show in a proper square shape and equal spacing on all sides?

2
  • Does this your questions answered? stackoverflow.com/a/65890000/14733292 Commented Feb 16, 2021 at 12:33
  • @RajaKishan Thanks. I gave it a try. It also works but I don't want to hardcode the number of rows. Commented Feb 16, 2021 at 13:42

1 Answer 1

1

MenuButton has fixed width and height, thats why it behaves incorrectly.


You could utilise .aspectRatio and .frame(maxWidth: .infinity, maxHeight: .infinity) for this:

struct MenuButton: View {
    let title: String
    let icon: Image

    var body: some View {
        Button(action: {
            print(#function)
        }) {
            VStack(spacing: 10) {
                icon
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(maxWidth: 60, maxHeight: 60)
                Text(title)
                    .foregroundColor(.black)
                    .font(.system(size: 20, weight: .bold))
                    .multilineTextAlignment(.center)
            }
            .padding()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .aspectRatio(1, contentMode: .fill)
        .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color. fr_primary, lineWidth: 0.6))
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the response. That indeed fixed my cell sizing issue. However there's a small problem. Even though the cell resizes, the content inside (image and the text) are still the same size. So in smaller screens, it looks like this. Is there a way to resize those elements to fit inside the cell as well?
I tried setting the aspect ratio to the Text object. It's pushing out the image.
@Isuru I assume you want to keep your buttons square.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.