HStack 等间距填充整个宽度

问题描述 投票:0回答:9

我有一个 HStack:

struct BottomList: View {
    var body: some View {
        HStack() {
            ForEach(navData) { item in
                NavItem(image: item.icon, title: item.title)
            }
        }
    }
}

*如何将其内容完美居中,等间距自动填充整个宽度?

仅供参考,就像 Bootstraps CSS 类

.justify-content-around

swift swiftui
9个回答
226
投票

可以使用

frame
布局修改器以及
.infinity
参数来实现此目的,而不需要额外的
maxWidth
视图。

Shape

Comparison using .frame modifier


29
投票
struct ContentView: View { var data = ["View", "V", "View Long"] var body: some View { VStack { // This will be as small as possible to fit the data HStack { ForEach(data, id: \.self) { item in Text(item) .border(Color.red) } } // The frame modifier allows the view to expand horizontally HStack { ForEach(data, id: \.self) { item in Text(item) .frame(maxWidth: .infinity) .border(Color.red) } } } } }

...但对于最后一个项目,不要

添加 
Spacer():
Spacer()

即使项目宽度不同,间隔均匀的示例列表:

(注意:接受的答案

struct BottomList: View { var body: some View { HStack() { ForEach(data) { item in Item(title: item.title) if item != data.last { // match everything but the last Spacer() } } } } }

并不适用于所有情况:当涉及到具有不同宽度的项目时,它对我不起作用)

    

各种

18
投票
类型将尝试缩小到可能包含其子视图的最小尺寸。如果子视图具有理想的尺寸,则

*Stack

 将不会扩展以填满屏幕。这可以通过将每个孩子放在 
*Stack
 中的透明 
Rectangle
 之上来克服,因为 
ZStack
 会尽可能地扩展。一个方便的方法是通过 
Shape
:
上的扩展
View

然后你可以这样称呼它:

extension View { func inExpandingRectangle() -> some View { ZStack { Rectangle() .fill(Color.clear) self } } }

您可以根据需要调整
struct ContentView: View {
    var data = ["View", "View", "View"]

    var body: some View {
        VStack {

            // This will be as small as possible to fit the items
            HStack {
                ForEach(data, id: \.self) { item in
                    Text(item)
                        .border(Color.red)
                }
            }

            // Each item's invisible Rectangle forces it to expand
            // The .fixedSize modifier prevents expansion in the vertical direction
            HStack {
                ForEach(data, id: \.self) { item in
                    Text(item)
                        .inExpandingRectangle()
                        .fixedSize(horizontal: false, vertical: true)
                        .border(Color.red)
                }
            }

        }
    }
}
上的间距。

如果项目是全角兼容的,它将自动完成,您可以将项目包裹在间隔符之间以实现它:

14
投票
HStack


所以你。可以在循环中使用它,例如:SingleView

struct Resizable: View { let text: String var body: some View { HStack { Spacer() Text(text) Spacer() } } }

您还可以在堆栈中使用

9
投票
...即

spacing

输出结果看起来像这样...

如果数组有重复值,请使用 array.indices 省略最后一个元素后面的间隔符。

6
投票
HStack(spacing: 30){ Image("NetflixLogo") .resizable() .scaledToFit() .frame(width: 40) Text("TV Show") Text("Movies") Text("My List") } .frame(maxWidth: .infinity)

我对接受的答案不满意,因为它们在 

4
投票

的前导和尾随两侧留下了额外的“伪填充”

这是我的解决方案的示例:

Hstack

结果如下:

提供的答案有问题

1
投票
由于提供的答案在各种情况下都能很好地工作,因此它们都没有创建类似于 CSS 的真正的

struct EvenlySpacedHStack: View { let items: [Int] = [1,2,3] var body: some View { ZStack() { Capsule().foregroundColor(.yellow) HStack() { ForEach(Array(items.enumerated()), id: \.element) { index, element in switch index { case items.count - 1: Image(systemName: "\(element).circle.fill") .resizable() .aspectRatio(1.0, contentMode: .fit) default: Image(systemName: "\(element).circle.fill") .resizable() .aspectRatio(1.0, contentMode: .fit) Spacer() } } } .padding(8) } .frame(height: 55) } }

间距行为,其中所有元素都等距分布,无论容器宽度如何。

当元素和 

space-between

没有足够的空间时,在元素之间仅使用普通的 Spacer

 可能会导致元素和文本在较小的容器中收缩和截断
,因为 Spacers
 还需要一些空间空间量。
所提供答案的结果可能如下所示:

解决方案

但是,您可以通过将

Spacer

minimumWidth

 设置为 0 并为所需元素分配更高的 
Spacers
来解决此问题,如下所示:
layoutPriority

通过这种技术,
无论容器大小如何,您都可以为视图实现真正的水平
struct SpaceBetweenView: View { var body: some View { HStack(spacing: 0) { ForEach(0..<6, id: \.self) { item in if item != 0 { Spacer() // Set the minWidth to 0 so the Spacer can shrink to 0 width // and doesn't block any space required for the Text view below. .frame(minWidth: 0) // <-- } Text("Item \(item)") .lineLimit(1) .background(Color.green) // Use a higher layoutPriority for the desired view to prevent it from shrinking // when there is not enough space in the container // for both (the Spacers and the elements). .layoutPriority(1) // <-- } } .frame(width: 300, height: 200) .border(Color.black) } } #Preview { SpaceBetweenView() }

行为。文本元素将不再因使用

space-between
而被截断,并且仅在存在时才会截断没有足够的空间容纳元素本身。
结果

在 Xcode 15.2、Swift 5、iOS 16.6 上测试

您只需为每个元素添加

0
投票
修饰符

.frame(maxWidth: .infinity)


© www.soinside.com 2019 - 2024. All rights reserved.