Joshua
Joshua

Reputation: 503

How to : Format Swift UI Buttons

I am figuring out Swift UI one step at a time. Here I have a VStack with a nested HStack setup holding some Buttons. I need to format them so they look a little less jumbled together.. what is the correct property to use? Is there a property I can use for the whole HStack view to handle this formatting automatically?

Simulator: https://gyazo.com/d566bc3ba8ea4de446f346d7098c1424

import SwiftUI

struct ContentView: View {
    
    var body: some View {
       ZStack {
        Color.init(hue: 0.2722, saturation: 0.89, brightness: 0.29, opacity: 1.0)        .edgesIgnoringSafeArea(.all)
             VStack {

                       HStack {

                           Button(action: {}){
                               Text("Today's List")
                                   .bold()
                                   .font(Font.custom("Helvetica Neue", size: 21.0))
                                   .padding(18)
                                   .foregroundColor(Color.white)
                                   .background(Color.green)
                                   .cornerRadius(12)
                               
                           }
                           Button(action: {}){
                               Text("Tomorrow's List")
                                   .bold()
                                   .font(Font.custom("Helvetica Neue", size: 21.0))
                                   .padding(18)
                                   .foregroundColor(Color.white)
                                   .background(Color.green)
                                   .cornerRadius(12)
                           }
                           
                           
                           
                           
                       }
                       VStack {
                           HStack {
                               Button(action: {}){
                                   Text("This Month")
                                       .bold()
                                       .font(Font.custom("Helvetica Neue", size: 21.0))
                                       .padding(18)
                                       .foregroundColor(Color.white)
                                       .background(Color.green)
                                       .cornerRadius(12)
                               }
                               Button(action: {}){
                                                               Text("Next Month")
                                                                   .bold()
                                                                   .font(Font.custom("Helvetica Neue", size: 21.0))
                                                                   .padding(18)
                                                                   .foregroundColor(Color.white)
                                                                   .background(Color.green)
                                                                   .cornerRadius(12)
                                                           }
                           }
                         
                       }
                       
                       VStack {
                                      HStack {
                                          Button(action: {}){
                                              Text("3% Yeild Or Higher")
                                                  .bold()
                                                  .font(Font.custom("Helvetica Neue", size: 21.0))
                                                  .padding(18)
                                                  .foregroundColor(Color.white)
                                                  .background(Color.green)
                                                  .cornerRadius(12)
                                          }
                                          Button(action: {}){
                                                                          Text("5% Yeild Or Higher")
                                                                              .bold()
                                                                              .font(Font.custom("Helvetica Neue", size: 21.0))
                                                                              .padding(18)
                                                                              .foregroundColor(Color.white)
                                                                              .background(Color.green)
                                                                              .cornerRadius(12)
                                                                      }
                                      }
                                    
                                  }
                       VStack {
                                              HStack {
                                                  Button(action: {}){
                                                      Text("App Help")
                                                          .bold()
                                                          .font(Font.custom("Helvetica Neue", size: 21.0))
                                                          .padding(18)
                                                          .foregroundColor(Color.white)
                                                          .background(Color.green)
                                                          .cornerRadius(12)
                                                  }
                                                  Button(action: {}){
                                                                                  Text("More Apps")
                                                                                      .bold()
                                                                                      .font(Font.custom("Helvetica Neue", size: 21.0))
                                                                                      .padding(18)
                                                                                      .foregroundColor(Color.white)
                                                                                      .background(Color.green)
                                                                                      .cornerRadius(12)
                                                                              }
                                              }
                                            
                                          }
                   }
                   
               }
        }
    }
        //Header
        
        
        //Data
        
        
        
        //Buttons
       






struct StrokeText: View {
    let text: String
    let width: CGFloat
    let color: Color
    
    var body: some View {
        ZStack{
            ZStack{
                Text(text).offset(x:  width, y:  width)
                Text(text).offset(x: -width, y: -width)
                Text(text).offset(x: -width, y:  width)
                Text(text).offset(x:  width, y: -width)
                
            }
            .foregroundColor(color)
            Text(text)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

EDIT: What can I do to make the buttons take this shape? Formatted into more of a box layout.

image for reference: https://gyazo.com/e142e7358083987f3ebde48b66841f52

Upvotes: 1

Views: 483

Answers (2)

Glenn Posadas
Glenn Posadas

Reputation: 13281

First off, you may want to refactor your code, clean it up. Say add a method that returns some View to generate Text objects for you. I haven't used SwiftUI much so it was interesting to me to go through your code for a couple of minutes.

import SwiftUI

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.init(hue: 0.2722, saturation: 0.89, brightness: 0.29, opacity: 1.0)        .edgesIgnoringSafeArea(.all)
            VStack(alignment: .center, spacing: 8) {
                HStack(alignment: .firstTextBaseline, spacing: 8) {
                    Button(action: {}){
                        self.newText("Today's List")
                    }
                    Button(action: {}){
                        self.newText("Tomorrow's List")
                    }
                }
                HStack(alignment: .firstTextBaseline, spacing: 8) {
                    Button(action: {}){
                        self.newText("This Month")
                    }
                    Button(action: {}){
                        self.newText("Next Month")
                    }
                }
                HStack(alignment: .firstTextBaseline, spacing: 8) {
                    Button(action: {}){
                        self.newText("% Yeild Or Higher")
                    }
                    Button(action: {}){
                        self.newText("5% Yeild Or Higher")
                    }
                }
                HStack(alignment: .firstTextBaseline, spacing: 8) {
                    Button(action: {}){
                        self.newText("App Help")
                    }
                    Button(action: {}){
                        self.newText("More Apps")
                    }
                }
            }
        }
    }
    
    func newText(_ text: String) -> some View {
        let text = Text(text)
            .bold()
            .font(Font.custom("Helvetica Neue", size: 21.0))
            .padding(18)
            .foregroundColor(Color.white)
            .background(Color.green)
            .cornerRadius(12)
        
        return text
    }
}

As you can see, you can remove the unnecessary VStacks, make a "Text factory" method that returns Text objects, utilize the stacks' alignment and spacing.

And here's your output:

enter image description here


Edit: You wanted to distribute the buttons equally? I took time to experiment, tinkering the views' frames.

You need to set the button's bg color instead of the text. And with that, you can refactor further your code by making a button factory method that returns some View.

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.init(hue: 0.2722, saturation: 0.89, brightness: 0.29, opacity: 1.0)        .edgesIgnoringSafeArea(.all)
            VStack(alignment: .center, spacing: 4) {
                HStack(alignment: .center, spacing: 4) {
                    self.newButton(text: "Today's List") { }
                    self.newButton(text: "Tomorrow's List") { }
                }
                HStack(alignment: .firstTextBaseline, spacing: 4) {
                    self.newButton(text: "This Month") { }
                    self.newButton(text: "Next Month")  { }
                }
                HStack(alignment: .firstTextBaseline, spacing: 4) {
                    self.newButton(text: "% Yeild Or Higher")  { }
                    self.newButton(text: "5% Yeild Or Higher")  { }
                }
                HStack(alignment: .firstTextBaseline, spacing: 4) {
                    self.newButton(text: "App Help")  { }
                    self.newButton(text: "More Apps")  { }
                }
            }
        }
    }
    
    func newButton(text: String, action: @escaping () -> Void) -> some View {
        let button = Button(action: action){
            self.newText(text)
        }.background(Color.green)
            .cornerRadius(12)
            .frame(minWidth: 0,
                   maxWidth: .infinity,
                   minHeight: 0,
                   maxHeight: 100.0)
        
        return button
    }
    
    func newText(_ text: String) -> some View {
        let text = Text(text)
            .bold()
            .font(Font.custom("Helvetica Neue", size: 21.0))
            .padding(8)
            .foregroundColor(Color.white)
            .frame(maxWidth: .infinity, maxHeight: 100.0)
        
        return text
    }
}

And here's your new output:

enter image description here

Upvotes: 1

Frankenstein
Frankenstein

Reputation: 16341

For a start, you can add padding to the VStacks. And do a bit of refactoring for VStack.

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.init(hue: 0.2722, saturation: 0.89, brightness: 0.29, opacity: 1.0)        .edgesIgnoringSafeArea(.all)
            VStack {
                CustomBlock(leading: "Today's List", trailing: "Tomorrow's List")
                CustomBlock(leading: "This Month", trailing: "Next Month")
                CustomBlock(leading: "3% Yeild Or Higher", trailing: "5% Yeild Or Higher")
                CustomBlock(leading: "App Help", trailing: "More Apps")
            }
        }
    }
}

struct CustomBlock: View {
    var leading: String
    var trailing: String
    var body: some View {
        VStack {
            HStack {
                Button(action: {}){
                    Text(leading)
                        .bold()
                        .font(Font.custom("Helvetica Neue", size: 21.0))
                        .padding(18)
                        .foregroundColor(Color.white)
                        .background(Color.green)
                        .cornerRadius(12)
                }
                Button(action: {}){
                    Text(trailing)
                        .bold()
                        .font(Font.custom("Helvetica Neue", size: 21.0))
                        .padding(18)
                        .foregroundColor(Color.white)
                        .background(Color.green)
                        .cornerRadius(12)
                }
            }

        }.padding()
    }
}

Upvotes: 1

Related Questions