SwiftUI中如何预测LazyVGrid内按钮的尺寸?
问题:SwiftUI中如何基于图标尺寸预测按钮的最小尺寸?
我想了解,在SwiftUI布局系统中,能否预测按钮的尺寸(哪怕只是最小尺寸)?我正将按钮放置在LazyVGrid中,按钮基于我指定尺寸的图标构建,但SwiftUI会根据上下文(如iOS环境、是否在表单内等)按HIG标准自动添加内边距。
我最初直接将LazyVGrid的最小列宽设为图标尺寸,但这并不正确,需要设置为包含SwiftUI自动添加内边距后的按钮尺寸。我不想使用自定义Layout或PreferenceKeys方案,想知道是否有基于图标尺寸的统一计算方式来得到准确的按钮尺寸,即便后续框架更新会导致该计算方式失效也无妨。
示例效果截图

示例代码
import SwiftUI let iconSize = 30.0 let iconSymbols = ["house", "applescript", "figure.stand"] struct ButtonsInLazyVGrid: View { var body: some View { LazyVGrid(columns: [GridItem(.adaptive(minimum: iconSize))]) { ForEach(iconSymbols, id: \.self) { symbol in Button { // do something } label: { Image(systemName: symbol) .resizable() .aspectRatio(contentMode: .fit) .frame(width: iconSize, height: iconSize) } .buttonStyle(.bordered) } }.padding() } }
解决方案
可以直接利用SwiftUI按钮样式的内置内边距常量来计算,以下是基于.bordered按钮样式的实践总结:
- 非表单环境:按钮的水平、垂直内边距各为
8pt(左右/上下各8),按钮总最小尺寸为图标尺寸 + 2*8,也就是iconSize + 16。 - 表单环境:
.bordered按钮内边距更大,水平内边距16pt、垂直内边距12pt,总最小尺寸为iconSize + 32(水平)、iconSize + 24(垂直)。
你只需将LazyVGrid的最小列宽设置为对应场景的计算值,就能让列宽刚好适配带内边距的按钮。修改后的非表单场景代码如下:
import SwiftUI let iconSize = 30.0 // 非表单环境下的按钮总最小尺寸 let buttonMinSize = iconSize + 16.0 let iconSymbols = ["house", "applescript", "figure.stand"] struct ButtonsInLazyVGrid: View { var body: some View { LazyVGrid(columns: [GridItem(.adaptive(minimum: buttonMinSize))]) { ForEach(iconSymbols, id: \.self) { symbol in Button { // do something } label: { Image(systemName: symbol) .resizable() .aspectRatio(contentMode: .fit) .frame(width: iconSize, height: iconSize) } .buttonStyle(.bordered) } }.padding() } }
注意:这些内边距值是基于当前HIG和SwiftUI版本的实践总结,若未来苹果调整按钮样式规范,该计算方式可能失效,但符合你"即便后续框架更新失效也无妨"的需求。
内容的提问来源于stack exchange,提问作者Curious Jorge
相关产品推荐
相关产品推荐

