如何在SwiftUI中限制文本的宽度

8

我尝试创建一个像这样的对话框:

Text("Hello my name is Johnny Miller and I am new here")
    .foregroundColor(.white)
    .padding()
    .background(.blue)
    .cornerRadius(25)

然而,我认为对话框的宽度比必要的宽了很多。因此,在气泡换行之前,我尝试限制其最大宽度。我想到的最简单的方法就是:

Text("Hello my name is Johnny Miller and I am new here")
    .foregroundColor(.white)
    .padding()
    .background(.blue)
    .cornerRadius(25)
    .frame(maxWidth: 300)  // << Limits how wide it can stretch

这适用于长消息,但当文本较小(如“Hello”)时,框架将保留在300个点,并拒绝调整为其理想宽度。

Frame staying at 300pts

我尝试使用 .fixedSize(),但当文本较长时会导致截断。

我找不到一种方法来限制文本的宽度并仍然以其理想大小显示。如果有人能提出解决方案,我将非常感激。

简而言之:文本框的宽度不应超过300个点,但高度可以任意。

谢谢!

编辑

到目前为止,我尝试了以下内容:

Text("Hello")
    .foregroundColor(.white)
    .padding()
    .background(.blue)
    .cornerRadius(25)
    .frame(maxWidth: 300)
    .lineLimit(nil)

这将导致“Hello”气泡具有300的边框(我已在上面提供了一张图像)

我尝试了以下方法:

Text("Hello my name is Johnny Miller and I am new here")
    .foregroundColor(.white)
    .padding()
    .background(.blue)
    .cornerRadius(25)
    .frame(maxWidth: 300)
    .lineLimit(nil)
    .fixedSize()

这使我获得了:

Truncated text


1
maxWidth: 300 对于长文本和短文本都能正常工作。在 Xcode 12.1 / iOS 14.1 上进行了测试。也许你的问题出在不同的代码上。 - Asperi
1
@Asperi,我添加了一张图片,你看到了吗? - rayaantaneja
1
同样的问题。你找到解决方案了吗? - Morpheus
1
同样的问题...这里肯定有解决方案...对吧? - Ruben Martinez Jr.
2个回答

1

解决方案

设置文本视图的背景,给文本视图设置最大宽度。

Text(message.content)
    .padding(.all,8)
    .background(Container()) // Container is a RoundedRectangle() with some styling
    .frame(maxWidth: 500, maxHeight: .infinity, alignment: .leading)

给你一些像这样的东西

解释

在SwiftUI中,文本视图会自动调整大小。

示例

您可以使用.frame(maxWidth: 500)之类的内容为文本设置maxWidth。

由于文本大小在设置了maxWidth后已经具有我们想要的行为,因此我们只需将其背景设置为某个视图即可。您还可以为其设置对齐方式和填充以匹配文本气泡效果,甚至是自定义形状。

我刚刚创建了一个名为Container()的视图,它只是带有样式的RoundedRectangle()。

struct Container: View {
    var body: some View {
        RoundedRectangle(cornerRadius: 12, style: .continuous)
            .fill(Color.container.opacity(1))
            .blendMode(.multiply)
            .shadow(color: .white.opacity(0.4), radius: 1, x: 0, y: 0)
            .shadow(color: .black.opacity(0.1), radius: 4, x: 2, y: 4)
    }
}

0

在这种情况下,我最终使用了UILabel。使用UILabel,我们可以设置preferredMaxLayoutWidth并设置内容抱紧优先级。

struct MaxWidthLabel: View {
    let text: String
    let textColor: Color
    let preferredMaxLayoutWidth: CGFloat

    init(_ text: String, textColor: Color, preferredMaxLayoutWidth: CGFloat) {
        self.text = text
        self.textColor = textColor
        self.preferredMaxLayoutWidth = preferredMaxLayoutWidth
    }

    @Environment(\.lineLimit)
    private var lineLimit: Int?

    var body: some View {
        Label(
            text,
            lineLimit: lineLimit,
            textAlignment: .center,
            textColor: UIColor(textColor),
            preferredMaxLayoutWidth: preferredMaxLayoutWidth
        )
    }
}

private struct Label: UIViewRepresentable {
    let text: String
    let lineLimit: Int?
    let textAlignment: NSTextAlignment
    let textColor: UIColor?
    let preferredMaxLayoutWidth: CGFloat

    init(
        _ text: String,
        lineLimit: Int? = nil,
        textAlignment: NSTextAlignment,
        textColor: UIColor? = nil,
        preferredMaxLayoutWidth: CGFloat
    ) {
        self.text = text
        self.lineLimit = lineLimit
        self.textAlignment = textAlignment
        self.textColor = textColor
        self.preferredMaxLayoutWidth = preferredMaxLayoutWidth
    }

    func makeUIView(context: UIViewRepresentableContext<Label>) -> UILabel {
        let label = UILabel(frame: .zero)
        label.numberOfLines = lineLimit ?? 0
        if let textColor = textColor {
            label.textColor = textColor
        }
        label.setContentHuggingPriority(.defaultHigh, for: .vertical)
        label.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
        label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
        label.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)

        updateUIView(label, context: context)
        return label
    }

    func updateUIView(_ label: UILabel, context: UIViewRepresentableContext<Label>) {
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.alignment = textAlignment

        let attrString = NSMutableAttributedString(string: text)
        attrString.addAttribute(
            NSAttributedString.Key.paragraphStyle,
            value: paragraphStyle,
            range: NSRange(location: 0, length: attrString.length)
        )

        label.attributedText = attrString
        label.preferredMaxLayoutWidth = preferredMaxLayoutWidth
    }
}

short content

long content


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接