SwiftUI:HStack 内的按钮导致整个 HStack 超出范围
SwiftUI: buttons inside a HStack cause the overall HStack to exceed the bounds
我有一个 SwiftUI,它在 HStack
中包含许多按钮。这些按钮有一个图标和一些垂直排列的文本。我 运行 遇到了按钮可能变得太宽的问题:HStack 超出了视图本身的范围。例如,如果“全部下载”按钮将其文本放在两行中,这是合乎逻辑的,但它并没有这样做。
预览示例:
如您所见,第一个版本有问题,三个按钮不再适合。但即使在第二个示例中,圆角也没有完全显示 - 只有第三个示例 100% 正确显示。
代码:
import SwiftUI
struct TransferDetailsButtonsView: View {
enum ButtonType: Hashable {
case share
case download
case delete
fileprivate var imageName: String {
switch self {
case .share:
return "icon-share"
case .download:
return "icon-download"
case .delete:
return "icon-delete"
}
}
fileprivate var title: String {
switch self {
case .share:
return "Share"
case .download:
return "Download all"
case .delete:
return "Delete"
}
}
}
/// The button types you want to show
var buttonTypes: [ButtonType] = [.share, .download, .delete]
/// The action for the buttons
var action: (ButtonType) -> Void = { _ in }
var body: some View {
HStack(spacing: 0) {
Spacer(minLength: 20)
.frame(maxWidth: .infinity)
ForEach(buttonTypes, id: \.self) { button in
Button {
action(button)
} label: {
VStack(spacing: 8) {
Image(button.imageName)
Text(button.title)
.lineLimit(nil)
}
.fixedSize()
}
Spacer(minLength: 20)
.frame(maxWidth: .infinity)
}
}
.padding(.vertical, 12)
.foregroundColor(.white)
.background(RoundedRectangle(cornerRadius: 16).fill(.blue))
}
}
struct TransferDetailsButtonsView_Previews: PreviewProvider {
static var previews: some View {
Group {
TransferDetailsButtonsView()
.frame(width: 260)
.previewLayout(.sizeThatFits)
TransferDetailsButtonsView()
.frame(width: 300)
.previewLayout(.sizeThatFits)
TransferDetailsButtonsView()
.frame(width: 420)
.previewLayout(.sizeThatFits)
}
}
}
如何才能使 HStack
不超出整体范围,而是将多行文本用于按钮文本?
您的 fixedSize()
使其将 HStack
绘制到边界之外。您希望文本填充可用的 space,然后 SwiftUI 将尝试中断单词。如果容器太小,它会在文字中破裂,因此您需要注意这一点,260 大约是该字体大小可以使用的最小值。
这是我想出的,修改为可以使用 SF 符号运行。您需要在文本之间进行一些填充,否则它们将在容器的某些尺寸下相互对齐。
struct TransferDetailsButtonsView: View {
enum ButtonType: Hashable {
case share
case download
case delete
fileprivate var imageName: String {
switch self {
case .share:
return "square.and.arrow.up.fill"
case .download:
return "square.and.arrow.up.fill"
case .delete:
return "square.and.arrow.up.fill"
}
}
fileprivate var title: String {
switch self {
case .share:
return "Share"
case .download:
return "Download all"
case .delete:
return "Delete it now"
}
}
}
/// The button types you want to show
var buttonTypes: [ButtonType] = [.share, .download, .delete]
/// The action for the buttons
var action: (ButtonType) -> Void = { _ in }
var body: some View {
HStack(alignment: .top, spacing: 0) {
ForEach(buttonTypes, id: \.self) { button in
Button {
action(button)
} label: {
VStack(spacing: 8) {
Image(systemName: button.imageName)
Text(button.title)
.frame(maxWidth: .infinity)
}
}
.padding(.horizontal, 4)
}
}
.padding(.vertical, 12)
.foregroundColor(.white)
.background(RoundedRectangle(cornerRadius: 16).fill(.blue))
}
}
我有一个 SwiftUI,它在 HStack
中包含许多按钮。这些按钮有一个图标和一些垂直排列的文本。我 运行 遇到了按钮可能变得太宽的问题:HStack 超出了视图本身的范围。例如,如果“全部下载”按钮将其文本放在两行中,这是合乎逻辑的,但它并没有这样做。
预览示例:
如您所见,第一个版本有问题,三个按钮不再适合。但即使在第二个示例中,圆角也没有完全显示 - 只有第三个示例 100% 正确显示。
代码:
import SwiftUI
struct TransferDetailsButtonsView: View {
enum ButtonType: Hashable {
case share
case download
case delete
fileprivate var imageName: String {
switch self {
case .share:
return "icon-share"
case .download:
return "icon-download"
case .delete:
return "icon-delete"
}
}
fileprivate var title: String {
switch self {
case .share:
return "Share"
case .download:
return "Download all"
case .delete:
return "Delete"
}
}
}
/// The button types you want to show
var buttonTypes: [ButtonType] = [.share, .download, .delete]
/// The action for the buttons
var action: (ButtonType) -> Void = { _ in }
var body: some View {
HStack(spacing: 0) {
Spacer(minLength: 20)
.frame(maxWidth: .infinity)
ForEach(buttonTypes, id: \.self) { button in
Button {
action(button)
} label: {
VStack(spacing: 8) {
Image(button.imageName)
Text(button.title)
.lineLimit(nil)
}
.fixedSize()
}
Spacer(minLength: 20)
.frame(maxWidth: .infinity)
}
}
.padding(.vertical, 12)
.foregroundColor(.white)
.background(RoundedRectangle(cornerRadius: 16).fill(.blue))
}
}
struct TransferDetailsButtonsView_Previews: PreviewProvider {
static var previews: some View {
Group {
TransferDetailsButtonsView()
.frame(width: 260)
.previewLayout(.sizeThatFits)
TransferDetailsButtonsView()
.frame(width: 300)
.previewLayout(.sizeThatFits)
TransferDetailsButtonsView()
.frame(width: 420)
.previewLayout(.sizeThatFits)
}
}
}
如何才能使 HStack
不超出整体范围,而是将多行文本用于按钮文本?
您的 fixedSize()
使其将 HStack
绘制到边界之外。您希望文本填充可用的 space,然后 SwiftUI 将尝试中断单词。如果容器太小,它会在文字中破裂,因此您需要注意这一点,260 大约是该字体大小可以使用的最小值。
这是我想出的,修改为可以使用 SF 符号运行。您需要在文本之间进行一些填充,否则它们将在容器的某些尺寸下相互对齐。
struct TransferDetailsButtonsView: View {
enum ButtonType: Hashable {
case share
case download
case delete
fileprivate var imageName: String {
switch self {
case .share:
return "square.and.arrow.up.fill"
case .download:
return "square.and.arrow.up.fill"
case .delete:
return "square.and.arrow.up.fill"
}
}
fileprivate var title: String {
switch self {
case .share:
return "Share"
case .download:
return "Download all"
case .delete:
return "Delete it now"
}
}
}
/// The button types you want to show
var buttonTypes: [ButtonType] = [.share, .download, .delete]
/// The action for the buttons
var action: (ButtonType) -> Void = { _ in }
var body: some View {
HStack(alignment: .top, spacing: 0) {
ForEach(buttonTypes, id: \.self) { button in
Button {
action(button)
} label: {
VStack(spacing: 8) {
Image(systemName: button.imageName)
Text(button.title)
.frame(maxWidth: .infinity)
}
}
.padding(.horizontal, 4)
}
}
.padding(.vertical, 12)
.foregroundColor(.white)
.background(RoundedRectangle(cornerRadius: 16).fill(.blue))
}
}