如何在SwiftUI中使视图的宽度等于父视图

59

我有一个按钮

在此输入图片描述

struct ContentView : View {
    var body: some View {
        HStack {
            Button(action: {}) {
                Text("MyButton")
                    .color(.white)
                    .font(Font.system(size: 17))
            }
            .frame(height: 56)
            .background(Color.red, cornerRadius: 0)
        }
    }
}

但我想将它固定在superview的边缘上(trailing与superview的trailing和leading对齐),就像这样:

enter image description here

HStack 对我没有帮助,而且它需要一个固定的frame或者宽度等于UIScree.size都不是灵活的解决方案。

6个回答

108

您需要使用.frame(minWidth:0,maxWidth:.infinity)修饰符

添加下一个代码

        Button(action: tap) {
            Text("Button")
                .frame(minWidth: 0, maxWidth: .infinity)
                .background(Color.red)
        }
        .padding(.horizontal, 20)

填充修饰符将允许您与边缘保持一定的间距。

请记住,修饰符的顺序非常重要。因为修饰符是包装下面视图的函数(它们不会改变视图的属性)。


3
".infinity"是个好东西,谢谢!但是将一些元素设置为superview是不可能的。但是如果将".frame(minWidth: 0, maxWidth: .infinity)"设置给"Text",并且在"Button"上添加"padding()",它就可以工作了!" - Argas
1
我该如何为按钮添加特定的高度?比如说,如果我要将按钮的高度设置为43像素,我该怎么做? - Gautam Shrivastav
2
一个小的补充是,现在你可以使用.padding(.horizontal, 20),如果你想要两侧都有填充,而不必单独提及左右。 - perte
为什么设置minWidth: 0?当我将其删除时,发现我的视图比父视图更大。我不理解这里的逻辑。 - GrandSteph
.frame(width: UIScreen.main.bounds.size.width - 32 , height: 48, alignment: .center) 不要使用padding。这也可以运作。 - Shrikant Phadke

31

1
我可以确认这个代码可以将按钮设置为整个宽度,但是我似乎无法在按钮的任何一侧添加填充。 - user3565259
7
不要将代码添加为图片。 - arun siva
我编辑了一些代码示例,基于这个解决方案。 - Climbatize

7
这里有一个纯SwiftUI解决方案,可以填充父视图的宽度,但将高度限制为任意纵横比(例如你想要正方形图片):
        Image("myImage")
            .resizable()
            .scaledToFill()
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .aspectRatio(16.0 / 9.0, contentMode: .fit)

只需将16.0 / 9.0替换为您想要的任何宽高比即可。

我花了大约一天时间去尝试解决这个问题,因为我不想使用GeometryReader或UIScreen.main.bounds(这不是跨平台的)。

编辑:找到了更简单的方法。


5

只需在代码中添加以下内容,即可使按钮延伸到边缘。如果需要,您还可以添加填充。

.frame(minWidth: 0, maxWidth: .infinity)

整个按钮代码将如下所示:
struct ContentView : View {
    var body: some View {
        HStack {
            Button(action: {}) {
                Text("MyButton")
                    .color(.white)
                    .font(Font.system(size: 17))
            }
            .frame(minWidth: 0, maxWidth: .infinity)
            .padding(.top, 8)
            .padding(.bottom, 8)
            .background(Color.red, cornerRadius: 0)
        }
    }
}

2
我找到了一个解决方案:

我发现一个解决方案:

var body: some View {
    Button(action: {}) {
            HStack {
                Spacer()
                Text("MyButton")
                    .color(.white)
                    .font(Font.system(size: 17))
                Spacer()
            }
            .frame(height: 56)
            .background(Color.red, cornerRadius: 0)
        }.padding(20)
}

但我不确定这是最好的解决方案。也许有人会找到更优雅的解决方案。原始答案翻译成“最初的回答”。

1
这里的一个问题是按钮可在其可见范围之外被点击。这意味着用户可能会错误地点击按钮,即使他们只是点击了空白处。 - Zorayr

2

iOS 17

从iOS 17开始,正确的做法是使用.containerRelativeFrame修饰符,因为在框架上使用.infinity宽度实际上会使父级框架具有无限宽度。

所以应该这样写:

Button(action: {}) {
    Text("MyButton")
        .foregroundStyle(.white)
        .containerRelativeFrame(.horizontal) //  This should be inside the `label` parameter of the `button`. Otherwise it would be NOT touchable
        .padding(-10) //  This is here to make space to the edges. Yes it should have a NEGATIVE value
}
.frame(height: 56)
.background(.red)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接