Home > Mobile >  How do I make an HStack of SwiftUI buttons have height?
How do I make an HStack of SwiftUI buttons have height?

Time:09-16

I have a simple SwiftUI row of buttons to mimic a keyboard layout. Just can't get the buttons to fill the height of the HStack. I can't tell where I need to give something height so it will look like a keyboard. No matter where I try to add height, the buttons still are small. macOS screenshot

struct KeyboardView: View {
  let rows = [String.keyboardFKeyRow, String.keyboardNumKeyRow, String.alpha1KeyRow, String.alpha2KeyRow, String.alpha3KeyRow, String.arrowKeyRow]
  var body: some View {
    VStack() {
      KeyRow(labels: String.keyboardFKeyRow).frame(height: 100)
      KeyRow(labels: String.keyboardNumKeyRow).frame(height: 100)
      KeyRow(labels: String.alpha1KeyRow).frame(height: 100)
      KeyRow(labels: String.alpha2KeyRow).frame(height: 100)
      KeyRow(labels: String.alpha3KeyRow).frame(height: 100)
      KeyRow(labels: String.arrowKeyRow).frame(height: 100)
    }
  }
}

struct KeyRow: View {
  var labels: [String]
  
  var body: some View {
    HStack() {
      Spacer()
      ForEach(labels, id: \.self) { label in
        Button {
          print("Key Clicked")
        } label: {
          Text(label.capitalized)
            .font(.body)
            .frame(minWidth: 60, maxWidth: 80, minHeight: 80, maxHeight: .infinity)
        }
      }
      Spacer()
    }
  }
}

CodePudding user response:

The .bordered button style on macOS has a hard-coded size and refuses to stretch vertically. If you need a different button height, either use the .borderless style or create your own ButtonStyle or PrimitiveButtonStyle, and (either way) draw the background yourself. For example, I got this result:

A row of three buttons. The first two buttons are both slightly bigger than their text labels. The third button has expanded to fill the container vertically.

from this playground:

import PlaygroundSupport
import SwiftUI

PlaygroundPage.current.setLiveView(HStack {

    // Default button style, Text label.
    Button("a", action: {})
        .background { Rectangle().stroke(.mint.opacity(0.5), lineWidth: 1).clipped() }
        .frame(maxHeight: .infinity)

    // Default button style, vertically greedy Text label.
    Button(action: {}, label: {
        Text("b")
            .frame(maxHeight: .infinity)
    })
    .background { Rectangle().stroke(.mint.opacity(0.5), lineWidth: 1).clipped() }
    .frame(maxHeight: .infinity)

    Button(action: {}, label: {
        Text("c")
            .fixedSize()
            .padding()
            .frame(maxHeight: .infinity)
            .background {
                RoundedRectangle(cornerRadius: 10)
                    .fill(Color(nsColor: .controlColor))
            }
    }).buttonStyle(.borderless)
        .background { Rectangle().stroke(.mint.opacity(0.5), lineWidth: 1).clipped() }
        .frame(maxHeight: .infinity)

}
    .background { Rectangle().stroke(.red.opacity(0.5), lineWidth: 1).clipped() }
    .frame(height: 100)
)
  • Related