【问题标题】:SwiftUI: buttons inside a HStack cause the overall HStack to exceed the boundsSwiftUI:HStack 中的按钮会导致整个 HStack 超出范围
【发布时间】:2022-01-19 03:33:26
【问题描述】:

我有一个 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 不超出总体范围,而是将多行文本用于按钮文本?

【问题讨论】:

  • 在 SwiftUI 中,默认情况下,容器适合内容,但反之则不行。因此,在您的情况下,HStack 只是环绕按钮,它们根据需要消耗尽可能多的空间。如果你想要相反,你需要以某种方式修复大小(取决于你需要什么)。可能使用外部 GeometryReader 和 HStack 上的框架来修复它。然后内部内容会以某种方式对有限的空间做出反应。

标签: swiftui hstack


【解决方案1】:

您的fixedSize() 使其将HStack 绘制在其边界之外。您希望 Texts 填充可用空间,然后 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))
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-18
    • 2013-09-25
    • 2020-12-01
    • 2021-12-15
    • 2013-02-11
    • 2012-02-16
    相关资源
    最近更新 更多