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

wgeznvg7  于 2023-01-10  发布在  iOS
关注(0)|答案(3)|浏览(368)

我正在尝试创建两个按钮,宽度相等,位置一个在另一个之上,垂直。它应该看起来像这样:

我在一个VStack里面放了2个Buttons,它会自动扩展到更大按钮的宽度。我试图做的是让按钮的宽度扩展到VStack的宽度,但这是我得到的结果:

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)

所以我的问题是:

除了手动设置版面中每个项目的框架外,是否还有其他方法可以实现此操作?

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

dgtucam1

dgtucam11#

.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)

tvz2xvvm

tvz2xvvm2#

您必须在按钮内部的Text上使用带有maxWidth: .infinity的框架修饰符,这将强制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中有效,但在使用默认按钮样式的macOS中无效。macOS使用AppKit的NSButton,因为它拒绝变宽(或变高)。macOS中的技巧是在按钮上使用.buttonStyle()修饰符(或NavigationLink),然后创建自己的自定义按钮样式,如下所示:

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

之所以必须将框架修饰符应用于Text视图而不是按钮本身,是因为按钮更喜欢保持其内容的大小,而不是包含按钮的视图建议的大小。这意味着如果将框架修饰符应用于按钮而不是按钮内部的Text,按钮实际上将保持与Text相同的大小,并且.frame返回的视图将扩展以填充包含它的视图的宽度,因此您将无法在Text视图的边界之外点击/单击按钮。

oipij1gg

oipij1gg3#

如果您希望匹配VStack的动态宽度,即:只占用它所需的空间(基于子视图的动态宽度)。您可以通过向父VStack添加.fixedSize(horizontal:,vertical:)修饰符来实现这一点。
示例:

var body: some View {
    VStack {
        Button("Log in") { }
            .foregroundColor(.white)
            .padding()
            .frame(maxWidth: .infinity)
            .background(.red)
            .clipShape(Capsule())
        
        Button("Reset Password") { }
            .foregroundColor(.white)
            .padding()
            .frame(maxWidth: .infinity)
            .background(.red)
            .clipShape(Capsule())
    }
    // Tells SwiftUI that the child views should only take up the space they need.
    .fixedSize(horizontal: true, vertical: false)
}

相关问题