SwiftUI:如何调整大小以适合按钮以展开以填充VStack或HStack父视图?

时间:2019-07-19 09:43:37

标签: ios swift user-interface swiftui

我正在尝试创建2个等宽的按钮,两个按钮垂直放置。它应该看起来像这样:

Two equal-width buttons positioned vertically with space between them

我在Buttons内放置了2个VStack,它会自动扩展到较大按钮的宽度。我正在尝试做的是将按钮的宽度扩展为填充VStack的宽度,但这是我得到的:

VStack auto sizing to largest button

VStack(alignment: .center, spacing: 20) {

    NavigationLink(destination: CustomView()) {
        Text("Button")
    }.frame(height: 44)
        .background(Color.primary)

    Button(action: { self.isShowingAlert = true }) {
        Text("Another Button")
    }.frame(height: 44)
        .background(Color.primary)

}.background(Color.secondary)

设置VStack的宽度会对其进行扩展,但是按钮不能进行扩展以适合:

VStack(alignment: .center, spacing: 20) {
    ...
}.frame(width: 320)
    .background(Color.secondary)

VStack width expands but Buttons do not

所以我的问题是:

除了手动设置布局中每个项目的框架之外,还有其他方法吗?

我宁愿不必指定每一个,因为这将变得难以管理。

2 个答案:

答案 0 :(得分:0)

.infinity设置为maxWidthframe(minWidth: maxWidth: minHeight:) API可用于使子视图展开以填充:

VStack(alignment: .center, spacing: 20) {

    NavigationLink(destination: CustomView()) {
        Text("Button")
    }.frame(minWidth: 100, maxWidth: .infinity, minHeight: 44)
        .background(Color.primary)

    Button(action: { self.isShowingAlert = true }) {
        Text("Another Button")
    }.frame(minWidth: 100, maxWidth: .infinity, minHeight: 44)
        .background(Color.primary)

}.frame(width: 340)
    .background(Color.secondary)

enter image description here

答案 1 :(得分:0)

您将不得不在按钮内maxWidth: .infinity本身上使用Text的frame修饰符,这将迫使Button变得尽可能宽:

VStack(alignment: .center, spacing: 20) {

    NavigationLink(destination: CustomView()) {
        Text("Button")
            .frame(maxWidth: .infinity, height: 44)
    }
    .background(Color.primary)

    Button(action: { self.isShowingAlert = true }) {
        Text("Another Button")
            .frame(maxWidth: .infinity, height: 44)
    }
    .background(Color.primary)

}.background(Color.secondary)

这适用于iOS,但不适用于使用默认按钮样式(使用AppKit的NSButton)的macOS,因为它拒绝变宽(或变高)。 macOS的窍门是在按钮(或.buttonStyle())上使用NavigationLink修饰符,然后像这样制作自己的自定义按钮样式:

struct MyButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .background(configuration.isPressed ? Color.blue : Color.gray)
    }
}

之所以必须将frame修饰符应用于Text视图而不是按钮本身的原因是,该按钮将倾向于坚持其内容的大小,而不是包含该按钮的视图所建议的大小。这意味着如果将frame修饰符而不是其中的Text应用于按钮,则按钮实际上将保持与Text相同的大小,并且由.frame返回的视图保持不变。是一个将展开以填充包含该视图的视图的宽度的视图,因此您将无法在Text视图的边界之外点击/单击按钮。