HStack默认布局导致视图不显示的问题
HStack默认布局导致视图不显示的问题

HStack默认布局导致视图不显示的问题

问题描述

在SwiftUI中,使用HStack + ForEach遍历内容,发现视图内容不显示。

例如,我想要实现的效果为:

在Xcode中使用HStack + ForEach没有显示国旗内容。

HStack {
    ForEach(countrys,id: \.self) { country in
        Image("\(country)")
            .resizable()
            .scaledToFit()
        Text(LocalizedStringKey(country))
            .font(.footnote)
    }
}

问题排查

当我给Image照片添加frame时,国旗才显示:

HStack {
    ForEach(countrys,id: \.self) { country in
        Image("\(country)")
            .resizable()
            .scaledToFit()
            .frame(width: 100)
        Text(LocalizedStringKey(country))
            .font(.footnote)
    }
}

同理,当给Text添加frame后,文字也会显示出来。

Text(LocalizedStringKey(country))
    .font(.footnote)
    .frame(minWidth: 100)

但是这里存在的一个问题就是,因为我的应用需要实现三十余种语言的本地化,某些语言的本地化名称较长,就会导致固定的frame并不能解决我的问题。

因此还需要寻找其他的解决方案。

解决方案

1、使用fixedSize()

明确Image设置frame,使用 fixedSize() 保障Text不被压缩。

HStack {
    ForEach(countrys,id: \.self) { country in
        Image("\(country)")
            .resizable()
            .scaledToFit()
            .frame(width: 100)
        Text(LocalizedStringKey(country))
            .font(.footnote)
            .fixedSize()
    }
}

fixedSize() 可以让 Text 保持原本的尺寸,不受父视图的压缩影响。

2、使用LazyHStack加载视图

LazyHStack {
    ForEach(countrys,id: \.self) { country in
        Image("\(country)")
            .resizable()
            .scaledToFit()
            .frame(width: 100)
        Text(LocalizedStringKey(country))
            .font(.footnote)
    }
}
.frame(width: width,height: 30)

HStack 会立即将所有子视图加载到内存中,并计算它们的尺寸,然后在 HStack 的布局规则下进行布局。

如果没有明确的 frame 或 Spacer(),HStack 会尝试压缩视图来适应内容,导致 Text 被压缩。

LazyHStack 则不同

它只加载当前可见的视图,并且在滚动时按需加载后续视图,因此不需要为所有内容提前计算布局。

由于 LazyHStack 不会预加载所有视图,它的布局机制更加灵活,避免了 HStack 可能出现的子视图被压缩的问题。

但需要注意的是,LazyHStack可能会让显示的视图变大,因此应该使用frame限制宽度和高度。

总结

在 HStack 中,Image 和 Text 没有设置明确的 frame 时,HStack 会尝试压缩视图以适应内容,导致:

1、Image 可能无法正常显示。

2、Text 被压缩到极小尺寸甚至隐藏。

核心原因为

1、HStack 立即加载所有子视图,并根据其内容大小布局。

2、如果没有明确 frame 或 Spacer(),HStack 会尝试缩小视图导致 Text 被挤压。

3、LazyHStack 由于按需加载视图,不会提前压缩内容,因此不会出现这个问题。

最后的解决方案为,Text使用 fixedSize() 防止被压缩。或者使用LazyHStack解决大数据量视图时的性能问题,同时防止Text被压缩。

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注