ios 如何在没有固定宽度的情况下让文本换行到UILabel中(通过UIViewRepresentable)?

sf6xfgos  于 2023-08-08  发布在  iOS
关注(0)|答案(3)|浏览(111)

将lineBreakMode设置为byWordWrapping并将numberOfLines设置为0似乎还不够:

struct MyTextView: UIViewRepresentable {
    func makeUIView(context: Context) -> UILabel {
        let label = UILabel()
        label.lineBreakMode = .byWordWrapping
        label.numberOfLines = 0
        label.text = "Here's a lot of text for you to display. It won't fit on the screen."
        return label
    }

    func updateUIView(_ view: UILabel, context: Context) {
    }
}

struct MyTextView_Previews: PreviewProvider {
    static var previews: some View {
        MyTextView()
            .previewLayout(.fixed(width: 300, height: 200))
    }
}

字符串
无论我对lineBreakMode使用哪种设置,文本都不会换行。画布预览和实时预览都是这样的:


的数据
我得到的最接近的是设置preferredMaxLayoutWidth,这确实会导致文本换行,但似乎没有一个值表示“无论View的大小”。

wnrlj8wa

wnrlj8wa1#

可能的解决方案是将宽度声明为MyTextView上的变量:

struct MyTextView: UIViewRepresentable {

    var width: CGFloat

    func makeUIView(context: Context) -> UILabel {
        let label = UILabel()
        label.lineBreakMode = .byWordWrapping
        label.numberOfLines = 0
        label.preferredMaxLayoutWidth = width
        label.text = "Here's a lot of text for you to display. It won't fit on the screen."
        return label
    }

    func updateUIView(_ view: UILabel, context: Context) {
    }
}

字符串
然后使用GeometryReader找出可用空间的大小,并将其传递到初始化器:

struct ExampleView: View {

    var body: some View {
        GeometryReader { geometry in
            MyTextView(width: geometry.size.width)
        }
    }
}

gmxoilav

gmxoilav2#

尝试在makeUIView()函数中使用这行代码

label.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

字符串

0g0grzrc

0g0grzrc3#

我发现了一种“讨厌”的方法,它允许UILabel在用作UIViewRepresentable时正确 Package (* 即使在ScrollView* 内),而不需要GeometryReader
每当创建UILabel时:

label.setContentCompressionResistancePriority(.defaultLow,
                                              for: .horizontal)
label.setContentHuggingPriority(.defaultHigh,
                                for: .vertical)

字符串
这可确保:

  • 标签将断开线且不具有无限宽度
  • 标签不会增加在某些情况下可能发生的不必要的高度增长。

然后...

  • width属性添加到UIViewRepresentable,该属性将用于设置preferredMaxLayoutWidth
  • 使用您的UIViewRepresentable到香草SwiftUI.View
  • 添加GeometryReader作为覆盖以防止扩展
  • 在软延迟后触发测量,修改一些状态以触发新的通过。
  • 即:*
public var body: some View {
        MyRepresentable(width: $width,
                        separator: separator,
                        content: fragments)
            .overlay(geometryOverlay)
            .onAppear { shouldReadGeometry = true }
    }

    // MARK: - Private Props

    @State private var width: CGFloat?
    @State private var shouldReadGeometry = false

    @ViewBuilder
    var geometryOverlay: some View {
        if shouldReadGeometry {
            GeometryReader { g in
                SwiftUI.Color.clear.onAppear {
                    self.width = g.size.width
                }
            }
        }
    }

旧答案:

...
在您的updateUIView(_:context:)中:

if let sv = uiView.superview, sv.bounds.width != 0 {
    let shouldReloadState = uiView.preferredMaxLayoutWidth != sv.bounds.width
    uiView.preferredMaxLayoutWidth = sv.bounds.width
    if shouldReloadState {
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
            self.stateToggle.toggle() // a Bool @State you can add in your struct
        }
    }
}

***免责声明:**我不是main.async调用的超级粉丝,特别是当它们与一些任意延迟结合使用时,但这似乎可以以一致的方式完成工作。

相关问题