SwiftUI中如何让HStack内两按钮取较宽按钮的宽度一致
问题描述
我正尝试创建一个包含两个按钮的HStack,代码如下:
struct SwiftUIView: View { var body: some View { HStack { Button("Short") { } Button("Rather long") { } } .buttonStyle(.bordered) } }
想要实现的效果是让两个按钮宽度相同,且都等于其中较宽按钮的宽度。
已尝试以下无法达到预期效果的方案:
fixedSize(horizontal: true, vertical: false)修饰符——仅在VStack中生效frame(maxWidth: .infinity)修饰符——虽有效果但会让按钮填满屏幕宽度,不符合设计需求frame(width: 80.0)——虽有效果但在标签文字变长或字号增大时失效
请问还有其他解决方案吗?
解决方案
方案一:自定义PreferenceKey获取最大宽度(兼容iOS 13+)
通过自定义PreferenceKey捕获两个按钮的宽度,取最大值后统一设置给两个按钮,代码实现如下:
// 定义用于传递宽度的PreferenceKey struct WidthPreferenceKey: PreferenceKey { static var defaultValue: CGFloat = 0 static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { value = max(value, nextValue()) } } struct SwiftUIView: View { @State private var maxButtonWidth: CGFloat = 0 var body: some View { HStack(spacing: 16) { // 可自定义按钮间距 Button("Short") { } .background( GeometryReader { geo in Color.clear .preference(key: WidthPreferenceKey.self, value: geo.size.width) } ) .frame(width: maxButtonWidth) Button("Rather long") { } .background( GeometryReader { geo in Color.clear .preference(key: WidthPreferenceKey.self, value: geo.size.width) } ) .frame(width: maxButtonWidth) } .buttonStyle(.bordered) .onPreferenceChange(WidthPreferenceKey.self) { newValue in maxButtonWidth = newValue } } }
方案二:使用Grid布局(iOS 16+)
iOS 16及以上提供的Grid布局默认会让同一行的元素宽度对齐,直接就能实现需求,代码更简洁:
struct SwiftUIView: View { var body: some View { Grid(horizontalSpacing: 16) { // 自定义按钮间距 GridRow { Button("Short") { } Button("Rather long") { } } } .buttonStyle(.bordered) } }
两种方案的特点:
- 方案一兼容性强,适配更早的iOS版本;
- 方案二代码简洁,适合已升级到iOS 16+的项目。
内容的提问来源于stack exchange,提问作者Malburrito
相关产品推荐
相关产品推荐

