Swiftui Text View Does Not Show Non-Displayable Characters

SwiftUI Text View does not show non-displayable characters

You can use Unicode.Scalar method escaped(asASCII: Bool) to convert unprintable characters to string:

func escaped(asASCII forceASCII: Bool) -> String

Scalar values representing characters that are normally unprintable or
that otherwise require escaping are escaped with a backslash.

extension StringProtocol {
var asciiEscaped: String {
unicodeScalars.map{$0.escaped(asASCII: true)}.joined()
}
}

Playground testing:

let str = "\0\u{11}\0\u{11}\0\u{11}\0\u{11}\0\u{11}"
print(str.asciiEscaped)

This will print:

\0\u{11}\0\u{11}\0\u{11}\0\u{11}\0\u{11}

SwiftUI get characters amount which are displayed

It's not a perfect solution and could be refactored but is works for both cases.

if more than 3 lines:

Sample Image

less than 3 lines:

Sample Image

import SwiftUI

struct ContentView: View {
let lineLimit: CGFloat = 3
@State var isTruncated: Bool = false
@State var size: CGSize = .zero

@State var value: String = "Provider 1, Provider 2, Provider 3, Provider 4, Provider 5, Provider 6, Provider 7, Provider 8, Provider 9, Provider 10, Provider 11, Provider 12, Provider 13, Provider 14, Provider 15, Provider 16, Provider 17, Provider 18, Provider 19, Provider 20, Provider 21, Provider 22, Provider 23, Provider 24, Provider 25, Provider 26, Provider 27, Provider 28, Provider 29, Provider 30, Provider 31, Provider 32, Provider 33, Provider 34, Provider 35, Provider 36, Provider 37, Provider 38, Provider 39, Provider 40, Provider 41, Provider 42, Provider 43, Provider 44, Provider 45, Provider 46, Provider 47, Provider 48, Provider 49, Provider 50, Provider 51, Provider 52, Provider 53, Provider 54, Provider 55, Provider 56, Provider 57, Provider 58, Provider 59, Provider 60, Provider 61, Provider 62, Provider 63, Provider 64, Provider 65, Provider 66, Provider 67, Provider 68, Provider 69, Provider 70, Provider 71, Provider 72, Provider 73, Provider 74, Provider 75, Provider 76, Provider 77, Provider 78, Provider 79, Provider 80"

@State var visibleProviders: String = ""

var body: some View {
VStack {
if isTruncated {
Text(visibleProviders)

} else {
TruncableText(
text: Text(value),
lineLimit: Int(lineLimit)
) { (isTruncated, size) in
self.isTruncated = isTruncated
self.size = size
self.calcSize(size: size)
}
}

}
.padding()
}

func calcSize(size: CGSize) {

var providers = value.components(separatedBy: ", ")
var text: String = ""
var textSize: CGFloat {
text.widthOfString(usingFont: .preferredFont(forTextStyle: .headline))/lineLimit
}
var otherProvidersString: String {
" + \(providers.count) others"
}
var otherProvidersStringSize: CGFloat {
otherProvidersString.widthOfString(usingFont: .preferredFont(forTextStyle: .headline))/lineLimit
}

var valueSize: CGFloat {
value.widthOfString(usingFont: .preferredFont(forTextStyle: .headline))/lineLimit
}

var isSizeLess: Bool {
size.width > (textSize + otherProvidersStringSize) && valueSize > size.width
}

while isSizeLess {
if !providers.isEmpty, let firstProvider = providers.first {
text += firstProvider
providers.removeFirst()
}
if isSizeLess {
text += ", "
}
}

visibleProviders = text + otherProvidersString
}

}

struct TruncableText: View {
let text: Text
let lineLimit: Int?
@State private var intrinsicSize: CGSize = .zero
@State private var truncatedSize: CGSize = .zero
let isTruncatedUpdate: (_ isTruncated: Bool, _ size: CGSize) -> Void

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

public 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)
}
}

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

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

extension String {
func widthOfString(usingFont font: UIFont) -> CGFloat {
let fontAttributes = [NSAttributedString.Key.font: font]
let size = self.size(withAttributes: fontAttributes)
return size.width
}
}

Possible to make non-editable Text() secure?

try this, works for me:

Text(String(repeating: "⚫", count: content.count))

You can also use this:

Text(String(repeating: "\u{1F910}", count: content.count))


Related Topics



Leave a reply



Submit