1

I need implement next flow in my code: Show text(1 line) and if it is cut or clipped (not fully visible) I should remove them, I don't want scale text or make it in 2 lines

UnRewa
  • 2,462
  • 2
  • 29
  • 31

1 Answers1

1

so I found solution, this solution is compose from few different topics:

struct TruncatableText: View {
  let text: (() -> Text)
  let lineLimit: Int?
  @State private var intrinsicSize: CGSize = .zero
  @State private var truncatedSize: CGSize = .zero
  @State private var hide: Bool = false

  var body: some View {
    text()
      .lineLimit(lineLimit)
      .readSize { size in
        truncatedSize = size
        hide = truncatedSize != intrinsicSize
      }
      .background(
        text()
          .fixedSize(horizontal: false, vertical: true)
          .hidden()
          .readSize { size in
            intrinsicSize = size
            hide = truncatedSize != intrinsicSize
          }
      )
      .isShow(!hide)
  }
}

extension View {
  func readSize(onChange: @escaping (CGSize) -> Void) -> some View {
    background(
      GeometryReader { geometryProxy in
        Color.clear
          .preference(key: SizePreferenceKey.self, value: geometryProxy.size)
      }
    )
    .onPreferenceChange(SizePreferenceKey.self, perform: onChange)
  }
  
  @ViewBuilder func isShow(_ show: Bool) -> some View {
    if show {
      self
    } else {
      self.hidden()
    }
  }
}

struct SizePreferenceKey: PreferenceKey {
  static var defaultValue: CGSize = .zero
  static func reduce(value: inout CGSize, nextValue: () -> CGSize) {}
}

and using it:

 TruncatableText(
          text: {
            Text("title")
              .font(.system(size: 21, weight: .semibold))
              .foregroundColor(Color.blue)
          },
          lineLimit: 1
        )
UnRewa
  • 2,462
  • 2
  • 29
  • 31