Skip to content

Instantly share code, notes, and snippets.

@X901

X901/NaturalText Secret

Last active September 14, 2023 06:41
Show Gist options
  • Select an option

  • Save X901/44a07f65ec9e1b7c83b71b31b650f1f8 to your computer and use it in GitHub Desktop.

Select an option

Save X901/44a07f65ec9e1b7c83b71b31b650f1f8 to your computer and use it in GitHub Desktop.
Allow .natural on Text and TextEditor in SwiftUI
////
//NaturalText.swift
//NaturalText
//
//Created by Basel Baragabah on 18/02/2022.
//Copyright © 2022 Basel Baragabah. All rights reserved.
//
import SwiftUI
import NaturalLanguage
struct NaturalText: View {
@Environment(\.layoutDirection) private var layoutDirection
var text : String
var body: some View {
Text(text)
.frame(maxWidth: .infinity, alignment: naturalAlignment)
.multilineTextAlignment(naturalTextAlignment)
}
private var naturalAlignment: Alignment {
guard let dominantLanguage = dominantLanguage else {
// If we can't identify the strings language, use the system language's natural alignment
return .leading
}
switch NSParagraphStyle.defaultWritingDirection(forLanguage: dominantLanguage) {
case .leftToRight:
if layoutDirection == .rightToLeft {
return .trailing
} else {
return .leading
}
case .rightToLeft:
if layoutDirection == .leftToRight {
return .trailing
} else {
return .leading
}
case .natural:
return .leading
@unknown default:
return .leading
}
}
private var naturalTextAlignment: TextAlignment {
guard let dominantLanguage = dominantLanguage else {
// If we can't identify the strings language, use the system language's natural alignment
return .leading
}
switch NSParagraphStyle.defaultWritingDirection(forLanguage: dominantLanguage) {
case .leftToRight:
if layoutDirection == .rightToLeft {
return .trailing
} else {
return .leading
}
case .rightToLeft:
if layoutDirection == .leftToRight {
return .trailing
} else {
return .leading
}
case .natural:
return .leading
@unknown default:
return .leading
}
}
private var dominantLanguage: String? {
let firstChar = "\(text.first ?? " ")"
return NLLanguageRecognizer.dominantLanguage(for: firstChar)?.rawValue
}
}
////
//NaturalTextEditor.swift
//NaturalText
//
//Created by Basel Baragabah on 18/02/2022.
//Copyright © 2022 Basel Baragabah. All rights reserved.
//
import SwiftUI
import NaturalLanguage
struct NaturalTextEditor: View {
@Environment(\.layoutDirection) private var layoutDirection
@Binding var text: String
var body: some View {
ZStack {
TextEditor(text: $text)
.frame(alignment: naturalAlignment)
.multilineTextAlignment(naturalTextAlignment)
.onAppear {
UITextView.appearance().backgroundColor = .clear
}
}
}
private var naturalAlignment: Alignment {
guard let dominantLanguage = dominantLanguage else {
// If we can't identify the strings language, use the system language's natural alignment
return .leading
}
switch NSParagraphStyle.defaultWritingDirection(forLanguage: dominantLanguage) {
case .leftToRight:
if layoutDirection == .rightToLeft {
return .trailing
} else {
return .leading
}
case .rightToLeft:
if layoutDirection == .leftToRight {
return .trailing
} else {
return .leading
}
case .natural:
return .leading
@unknown default:
return .leading
}
}
private var naturalTextAlignment: TextAlignment {
guard let dominantLanguage = dominantLanguage else {
// If we can't identify the strings language, use the system language's natural alignment
return .leading
}
switch NSParagraphStyle.defaultWritingDirection(forLanguage: dominantLanguage) {
case .leftToRight:
if layoutDirection == .rightToLeft {
return .trailing
} else {
return .leading
}
case .rightToLeft:
if layoutDirection == .leftToRight {
return .trailing
} else {
return .leading
}
case .natural:
return .leading
@unknown default:
return .leading
}
}
private var dominantLanguage: String? {
let firstChar = "\(text.first ?? " ")"
return NLLanguageRecognizer.dominantLanguage(for: firstChar)?.rawValue
}
}
struct NaturalTextEditor_Previews: PreviewProvider {
static var previews: some View {
NaturalTextEditor(text: .constant("Test !!"))
}
}
@X901
Copy link
Copy Markdown
Author

X901 commented Feb 18, 2022

The code above is detected the app layout direction and text content to decide if the text should be RTL or LTR
That means it won't change depending on layout direction only as you can see on the image below

Text
instead of using Text , use NaturalText
NaturalText(text: "Try one line of text")

TextEditor
instead of TextEditor, use NaturalTextEditor

 NaturalTextEditor(text: $text)
.background(.gray.opacity(0.2))

Notice here the app uses RTL language (Arabic) but the text show depend on text content, not app layout direction (default)

154735967-b665e3e4-9823-4b5f-abb3-0b4ba36e0fc5

on This Video, you will see how the TextEditor will change direction depending on text content direction

Feb-18-2022.18-18-32.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment