skip to Main Content

I am a novice to iOS and swift programming language. I am trying to create a home page for an app and I have two buttons in it.

import SwiftUI

struct HomePage: View {

  var body: some View {
    ZStack {
        // Background gradient
        LinearGradient(gradient: Gradient(colors: [.blue, .green]), startPoint: .topLeading, endPoint: .bottomTrailing)
        .ignoresSafeArea()
        let footballLoginButton = CustomButton()
        let baseballLoginButton = CustomButton()
        VStack(spacing: 40) {
            // App Logo (replace with your actual logo)
            Image("your_app_logo")
              .resizable()
              .scaledToFit()
              .frame(width: 150, height: 70)

            Text("Select your sport:")
              .font(.title)
              .fontWeight(.bold)
              .foregroundColor(.white)

            footballLoginButton.createBlueButton(withTitle: "football Login", height: 70, width: 250, color: "blue", systemName: "football", action: {
              // Your football login action code here
            })

            footballLoginButton.createGreenButton(withTitle: "baseball Login", height: 70, width: 250, color: "green", systemName: "baseball", action: {
              // Your football login action code here
            })

        }
    }
  }
}

struct HomePage_Previews: PreviewProvider {
  static var previews: some View {
    HomePage()
  }
}

I am using the below class to create buttons.

class CustomButton {
    
    func createBlueButton(withTitle title: String, height: CGFloat, width: CGFloat, color: String, systemName: String, action: @escaping () -> Void) -> some View {
        Button(action: {}) {
            HStack(spacing: 275) {
                Image(systemName: systemName)
                    .foregroundColor(.white)
                Text(title)
                    .fontWeight(.bold)
                    .foregroundColor(.white)
            }
            .padding()
            .background(Color.blue)
            .clipShape(RoundedRectangle(cornerRadius: 20)) // Squircle shape
            .frame(width: width, height: height) // Adjusted button size
        }
    }
    
    func createGreenButton(withTitle title: String, height: CGFloat, width: CGFloat, color: String, systemName: String, action: @escaping () -> Void) -> some View {
        Button(action: {}) {
            HStack(spacing: 275) {
                Image(systemName: systemName)
                    .foregroundColor(.white)
                Text(title)
                    .fontWeight(.bold)
                    .foregroundColor(.white)
            }
            .padding()
            .background(Color.green)
            .clipShape(RoundedRectangle(cornerRadius: 20)) // Squircle shape
            .frame(width: width, height: height) // Adjusted button size
        }
    }
}

But the app preview on XCode IDE shows buttons without text in it as below.
enter image description here

If I reduce the HStack’s spacing to 75 like HStack(spacing: 75) I am able to see the text in button but the buttons are very small. Could anyone let me know what is the mistake I am making here and how can I correct it?

Edit1

Also tried: .frame(width: width, height: height, alignment: .center) in the button class but the result is same.

2

Answers


  1. Reduce the spacing in HStack. In your case the spacing is 275, so try reducing it to 50 or 40 and you will start seeing the text. As 275 spacing exceeds the width of the button so the text goes outside the view of the button and hence you are not able to see it.

    The code below is the corrected code: –

    import SwiftUI
    
    struct HomePage: View {
    
      var body: some View {
        ZStack {
            // Background gradient
            LinearGradient(gradient: Gradient(colors: [.blue, .green]), startPoint: .topLeading, endPoint: .bottomTrailing)
            .ignoresSafeArea()
            let footballLoginButton = CustomButton()
            let baseballLoginButton = CustomButton()
            VStack(spacing: 40) {
                // App Logo (replace with your actual logo)
                Image("your_app_logo")
                .resizable()
                .scaledToFit()
                .frame(width: 150, height: 70)
    
                Text("Select your sport:")
                .font(.title)
                .fontWeight(.bold)
                .foregroundColor(.white)
    
                footballLoginButton.createBlueButton(withTitle: "football Login", height: 70, width: 250, color: "blue", systemName: "football", action: {
                          // Your football login action code here
                        })
    
                footballLoginButton.createGreenButton(withTitle: "baseball Login", height: 70, width: 250, color: "green", systemName: "baseball", action: {
                          // Your football login action code here
                        })
    
    
          }
        }
      }
    }
    
    class CustomButton {
        
        func createBlueButton(withTitle title: String, height: CGFloat, width: CGFloat, color: String, systemName: String, action: @escaping () -> Void) -> some View {
                Button(action: {}) {
                    HStack(spacing: 40) {
                        Image(systemName: systemName)
                            .foregroundColor(.white)
                        Text(title)
                            .fontWeight(.bold)
                            .foregroundColor(.white)
                    }
                    .padding()
                    .frame(width: width, height: height) // Adjusted button size
                    .background(Color.blue)
                    .clipShape(RoundedRectangle(cornerRadius: 20)) // Squircle shape
                    
                }
            }
            
            func createGreenButton(withTitle title: String, height: CGFloat, width: CGFloat, color: String, systemName: String, action: @escaping () -> Void) -> some View {
                Button(action: {}) {
                    HStack(spacing: 50) {
                        Image(systemName: systemName)
                            .foregroundColor(.white)
                        Text(title)
                            .fontWeight(.bold)
                            .foregroundColor(.white)
                    }
                    .padding()
                    .frame(width: width, height: height) // Adjusted button size
                    .background(Color.green)
                    .clipShape(RoundedRectangle(cornerRadius: 20)) // Squircle shape
                    
                }
            }
        
    }
    
    struct HomePage_Previews: PreviewProvider {
      static var previews: some View {
        HomePage()
      }
    }
    

    In createBlueButton() I have reduced the spacing to 40 and in createBlueButton() reduced the spacing to 50.

    And after Edit1…

    The frame modifier should be applied before the RoundedRectangle ClipShape and the background color modifier.
    This would make the size of button you wanted with the text visible.

    And yes the ordering of modifiers matters a lot in designing a component in SwiftUI

    All the changes are there in the above provided code.

    This is the result
    https://i.sstatic.net/69zL4FBM.png

    Hope it works….
    Thank You and Please Upvote

    Login or Signup to reply.
  2. I would suggest the following changes:

    • Instead of applying spacing to the HStack, use one or more Spacer() to provide the spacing:
    HStack {
        Image(systemName: systemName)
        Spacer()
        Text(title)
        Spacer()
    }
    
    • The reason why your attempts to set a frame width didn’t seem to be working may be because you need to set the width before you apply the background color. So the .frame modifier needs to come before the .background and .clipShape.

    • Your class CustomButton appears to be a button factory. However, there is no need to create an instance for each button. In fact, you have created two instances called footballLoginButton and baseballLoginButton, but you then use footballLoginButton to create both of the actual buttons, baseballLoginButton is not being used. So I would suggest changing the functions into static functions, and it can be a struct instead of a class too.

    • Instead of using a fixed width and height, just let the content find its own size and then use padding to add spacing where needed.

    • When it comes to button styling, it works well to define your own ButtonStyle.

    • The modifier .foregroundColor is deprecated, use .foregroundStyle instead.

    Here’s how it can all come together:

    struct HomePage: View {
    
        var body: some View {
            ZStack {
                // Background gradient
                LinearGradient(gradient: Gradient(colors: [.blue, .green]), startPoint: .topLeading, endPoint: .bottomTrailing)
                    .ignoresSafeArea()
                VStack(spacing: 40) {
                    // App Logo (replace with your actual logo)
                    Image("your_app_logo")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 150, height: 70)
    
                    Text("Select your sport:")
                        .font(.title)
                        .fontWeight(.bold)
                        .foregroundStyle(.white)
    
                    CustomButton.createBlueButton(withTitle: "football Login", systemName: "football") {
                        // Your football login action code here
                    }
    
                    CustomButton.createGreenButton(withTitle: "baseball Login", systemName: "baseball") {
                        // Your baseball login action code here
                    }
                }
                .padding(.horizontal, 30)
            }
        }
    }
    
    class CustomButton {
    
        private struct CustomButtonStyle: ButtonStyle {
            let color: Color
    
            func makeBody(configuration: Configuration) -> some View {
                configuration.label
                    .foregroundStyle(.white)
                    .fontWeight(.bold)
                    .padding()
                    .background(color)
                    .clipShape(RoundedRectangle(cornerRadius: 20)) // Squircle shape
            }
        }
    
        private static func createButton(withTitle title: String, systemName: String, color: Color, action: @escaping () -> Void) -> some View {
            Button(action: action) {
                HStack {
                    Image(systemName: systemName)
                    Spacer()
                    Text(title)
                    Spacer()
                }
            }
            .buttonStyle(CustomButtonStyle(color: color))
        }
    
        static func createBlueButton(withTitle title: String, systemName: String, action: @escaping () -> Void) -> some View {
            CustomButton.createButton(withTitle: title, systemName: systemName, color: .blue, action: action)
        }
    
        static func createGreenButton(withTitle title: String, systemName: String, action: @escaping () -> Void) -> some View {
            CustomButton.createButton(withTitle: title, systemName: systemName, color: .green, action: action)
        }
    }
    

    Screenshot

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search