I am trying to create a rich text editor that will allow the user to dynamically create text with Bold/Italic/Underline/Strikethrough as well as bullets and indents.
This is very similar to what I can see with the apple Notes app and I want a similar look and feel. Unfortunately this is not provided to us by Apple so I need to implement it myself. I am not looking for a third party library to do this.
I have begun by using a UIViewRepresentable with a UITextView and NSAttributedString.
My approach is to use get the NSRange of a paragraph and adjust the formatting based on the users' selections. This is quite tedious and especially with the bullet's I am having a lot of trouble.
So I thought I would pause and ask if I'm going about this the right way or if there is an easier way to add this functionality to my app. I have seen some using a WKWebView but there is very little information on that online.
I notice in the Notes app that the options for Font Size are Title/Heading/Subheading/Body/Monostyle. I don't see these matching any of the system font styles in iOS so wondering if this app is built with HTML and those are HTML font styles?
So far this is what I have which only deals with Bold/Italic etc... and only from that point forth. Not for the whole paragraph like the notes app. It also is not yet accounting for highlighting then adding bold.
The more I'm working through this the more I feel I am on the wrong path and there must be another way to achieve this.
struct AttributedTextEditor: UIViewRepresentable {
@Binding var text: NSAttributedString
@Binding var bold: Bool
@Binding var italic: Bool
@Binding var underline: Bool
@Binding var strike: Bool
func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.delegate = context.coordinator
return textView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.attributedText = text
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UITextViewDelegate {
var parent: AttributedTextEditor
init(_ parent: AttributedTextEditor) {
self.parent = parent
}
func textViewDidChange(_ textView: UITextView) {
parent.text = NSAttributedString(attributedString: textView.attributedText)
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
var traits = UIFontDescriptor().symbolicTraits
if parent.bold {
traits.insert([.traitBold])
}
if parent.italic {
traits.insert([.traitItalic])
}
if parent.underline {
textView.typingAttributes[NSAttributedString.Key.underlineStyle] = 1
} else {
textView.typingAttributes[NSAttributedString.Key.underlineStyle] = 0
}
if parent.strike {
textView.typingAttributes[NSAttributedString.Key.strikethroughStyle] = 1
} else {
textView.typingAttributes[NSAttributedString.Key.strikethroughStyle] = 0
}
let fontDescriptor = UIFontDescriptor().withSymbolicTraits(traits)
textView.typingAttributes[NSAttributedString.Key.font] = UIFont(descriptor: fontDescriptor!, size: 34)
return true
}
}
}
I have noticed that looking at the lower case 'a' of the notes app font that this is a variation of the SF font that is not available. So that might explain why the font's don't exactly match the system font.