mica
mica

Reputation: 4308

Let use a button all available width in SwiftUI on MacOS AppKit

I want to define a layout like this:

enter image description here

How can I let the Buttons grab all the available width, also when the user resizes the Window.
In the upper part three rows of equal width, in the lower part one row with max. width

struct TEST: View {
  let columns = [
    GridItem(.flexible()),
    GridItem(.flexible()),
    GridItem(.flexible())
  ]
  let data = ["1 Text ...",
              "2 longer Text ...",
              "3 Text ...",
              "4 Text/FA/Tra ...",
              "5 Text ...",
              "6 Text ...",
              "7 Text ...",
              "8 Text ...",
              "9  Text ...",
  ]

  var body: some View {
    VStack (alignment: .leading ){
      LazyVGrid(columns: columns) {
        ForEach(data, id: \.self) { item in
          Button(action: {print("")}){
            Text(item).background(Color.green)
          }
          .background(Color.yellow)
        }
      }
      .padding(.horizontal)
    }
    Button("even longer Text"){print("x")}
    Button("even longer Text"){print("x")}
    Button("even longer Text"){print("x")}
  }
}

Upvotes: 1

Views: 741

Answers (3)

Seun Tofunmi
Seun Tofunmi

Reputation: 1

You can use the frame(maxWidth: .infinity) command. However, the trick is to apply the width style to the label of the button itself as opposed to the actual button declaration.

Here is a sample code on how to do this in Swift UI

Button {
    doSomething()
} label: {
    Text("Click me").frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)

source

Upvotes: 0

pawello2222
pawello2222

Reputation: 54661

You can use .frame(maxWidth: .infinity):

Button("even longer Text") { 
    print("x") 
}
.frame(maxWidth: .infinity)

EDIT

Here is a more detailed example:

var body: some View {
    VStack(alignment: .leading) {
        LazyVGrid(columns: columns) {
            ForEach(data, id: \.self) { item in
                Button(action: { print("") }) {
                    Text(item)
                        .frame(maxWidth: .infinity)
                        .contentShape(Rectangle())
                }
                .background(Color.yellow)
            }
        }
        .padding(.horizontal)
        .background(Color.blue)
    }
    Button(action: { print("x") }) {
        Text("even longer Text")
            .frame(maxWidth: .infinity)
            .contentShape(Rectangle())
    }
    .background(Color.purple)
    ...
}

I added colors, so you can see that buttons are aligned properly.

enter image description here

Tested with Xcode 12.3, macOS 11.1

Upvotes: 1

mica
mica

Reputation: 4308

Found a solution:

struct TEST: View {

  let columns = [
    GridItem(.flexible()),
    GridItem(.flexible()),
    GridItem(.flexible())
  ]
  let data = ["1 Text ...",
              "2 longer Text ...",
              "3 Text ...",
              "4 Text/FA/Tra",
              "5 Text ...",
              "6 Text ...",
              "7 Text ...",
              "8 Text ...",
              "9  Text ...",
  ]

  var body: some View {
    VStack (alignment: .leading ){
      LazyVGrid(columns: columns) {
        ForEach(data, id: \.self) { item in
          ExpandingButton(s: item){print("pressed")}
        }
      }
      .padding(.horizontal)
    }
    ExpandingButton(s: "Hogo"){print("hogo")}
    ExpandingButton(s: "Hogo"){print("hogo")}
    ExpandingButton(s: "Hogo"){print("hogo")}

  }
}

struct ExpandingButton: View {
  var s : String
  var action: ()->Void

  var body: some View {
    HStack (alignment: .top){
      Spacer()
      Text(s)
       .padding(4)
      Spacer()
    }
    .background(Color.gray)
    .cornerRadius(4)
    .onTapGesture  {action()}
  }
}

Upvotes: 0

Related Questions