Swift - How to Get Text Formatting in a Text Editor Like in the Notes App? Swiftui

Swift - How to get text formatting in a text editor like in the notes app? SwiftUI

You can create a custom TextView UIViewRepresentable and set allowsEditingTextAttributes to true there:

create a new Swift file called TextView.swift

import SwiftUI
struct TextView: UIViewRepresentable {

@Binding var attributedText: NSMutableAttributedString
@State var allowsEditingTextAttributes: Bool = false
@State var font: UIFont?

func makeUIView(context: Context) -> UITextView {
UITextView()
}

func updateUIView(_ uiView: UITextView, context: Context) {
uiView.attributedText = attributedText
uiView.allowsEditingTextAttributes = allowsEditingTextAttributes
uiView.font = font
}
}

Then you can add it to your content view:

import SwiftUI

struct ContentView: View {
@State var attributedText = NSMutableAttributedString(string: "")
var body: some View {
TextView(attributedText: $attributedText, allowsEditingTextAttributes: true, font: .systemFont(ofSize: 32))
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
}
}

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

Sample Image

SwiftUI TextEditor - save the state after completion of editing

I don't know exactly what you mean to save once the editing is done. Here are two possible approaches I found.

Note:
In the following demos, the text with blue background displays the saved text.

1. Saving when user dismisses keyboard

Solution: Adding a tap gesture to let users dismiss the keyboard when tapped outside of the TextEditor. Call save() at the same time.

Code:

struct ContentView: View {

@State private var text: String = ""
@State private var savedText: String = ""


var body: some View {
VStack(spacing: 20) {
Text(savedText)
.frame(width: 300, height: 200, alignment: .topLeading)
.background(Color.blue)

TextEditor(text: $text)
.frame(width: 300, height: 200)
.border(Color.black, width: 1)
.onTapGesture {}
}
.onTapGesture { hideKeyboardAndSave() }
}


private func hideKeyboardAndSave() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
save()
}


private func save() {
savedText = text
}
}

2. Saving after no changes for x seconds

Solution: Using Combine with .debounce to publish and observe only after x seconds have passed with no further events.

I have set x to 3.

Code:

struct ContentView: View {

@State private var text: String = ""
@State private var savedText: String = ""

let detector = PassthroughSubject<Void, Never>()
let publisher: AnyPublisher<Void, Never>

init() {
publisher = detector
.debounce(for: .seconds(3), scheduler: DispatchQueue.main)
.eraseToAnyPublisher()
}


var body: some View {
VStack(spacing: 20) {
Text(savedText)
.frame(width: 300, height: 200, alignment: .topLeading)
.background(Color.blue)

TextEditor(text: $text)
.frame(width: 300, height: 200)
.border(Color.black, width: 1)
.onChange(of: text) { _ in detector.send() }
.onReceive(publisher) { save() }
}
}


private func save() {
savedText = text
}
}

SwiftUI - how to copy text to clipboard?

Use the following - put shown text into pasteboard for specific type (and you can set as many values and types as needed)

Update: for Xcode 13+, because of "'kUTTypePlainText' was deprecated in iOS 15.0..." warning

import UniformTypeIdentifiers

Text(self.BLEinfo.sendRcvLog)
.onTapGesture(count: 2) {
UIPasteboard.general.setValue(self.BLEinfo.sendRcvLog,
forPasteboardType: UTType.plainText.identifier)
}

for older versions:

import MobileCoreServices // << for UTI types

// ... other code

Text(self.BLEinfo.sendRcvLog)
.onTapGesture(count: 2) {
UIPasteboard.general.setValue(self.BLEinfo.sendRcvLog,
forPasteboardType: kUTTypePlainText as String)
}

Using iOS 5 rich text editor

The iOS 5 rich text edit control is also present in the notes app in iOS 4 (make a rich text note on the computer and sync it to see).

This is a custom Apple-made control which they use in their own apps, but it is not published in any official developer API. It's probably in the SDK somewhere, but because it is undocumented, even if you find it and use it, Apple will reject your app.

Basically, if you want a rich text control you will have to make your own.

Edit: Try using this: https://github.com/omnigroup/OmniGroup/tree/master/Frameworks/OmniUI/iPad/Examples/TextEditor/. I haven't used it, so I don't know how well it will work. (Link from this question)

How to use Attributed String in SwiftUI

iOS 15 and Swift 5.5

Text now supports markdown and also you can create custom attributes:

Sample Image

You can even get defined attributes remotely like:

Sample Image



iOS 13 and 14

You can combine multiple Text objects together with a simple + operator and that will handle some of the attributions:

Sample Image

Each one can have multiple and specific modifiers



A fully supported fallback!

Since it doesn't support directly on Text (till iOS 15), you can bring the UILabel there and modify it in anyway you like:

Implementation:

struct UIKLabel: UIViewRepresentable {

typealias TheUIView = UILabel
fileprivate var configuration = { (view: TheUIView) in }

func makeUIView(context: UIViewRepresentableContext<Self>) -> TheUIView { TheUIView() }
func updateUIView(_ uiView: TheUIView, context: UIViewRepresentableContext<Self>) {
configuration(uiView)
}
}

Usage:

var body: some View {
UIKLabel {
$0.attributedText = NSAttributedString(string: "HelloWorld")
}
}


Related Topics



Leave a reply



Submit