Created
November 4, 2020 22:21
-
-
Save lhoward/7537977a8073009f7cb1f44173c47994 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import SwiftUI | |
| struct AttributedTextView: TextView, UIViewRepresentable { | |
| let content: NSAttributedString | |
| @Binding var height: CGFloat | |
| var font: UIFont? = nil | |
| var textAlignment: NSTextAlignment = .left | |
| var lineBreakMode: NSLineBreakMode = .byWordWrapping | |
| var textColor: UIColor = UIColor.label | |
| var backgroundColor: UIColor = UIColor.clear | |
| var disableInteraction = false | |
| var disableContextMenuInteraction = false | |
| public func makeUIView(context: Context) -> UITextView { | |
| let textView = UITextView() | |
| textView.isEditable = false | |
| textView.isUserInteractionEnabled = !self.disableInteraction | |
| textView.isScrollEnabled = false | |
| textView.automaticallyAdjustsScrollIndicatorInsets = false | |
| textView.textContainer.lineFragmentPadding = 0 | |
| textView.textContainer.lineBreakMode = self.lineBreakMode | |
| textView.contentInset = .zero | |
| textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) | |
| textView.font = self.font ?? UIFont.with(font: .body) | |
| textView.adjustsFontForContentSizeCategory = true | |
| textView.textAlignment = self.textAlignment | |
| textView.textColor = self.textColor | |
| textView.backgroundColor = self.backgroundColor | |
| textView.contentSize = .zero | |
| if self.disableContextMenuInteraction, | |
| let contextMenuInteraction = textView.interactions.filter({ $0 is UIContextMenuInteraction }).first as? UIContextMenuInteraction { | |
| textView.removeInteraction(contextMenuInteraction) | |
| } | |
| if let font = self.font { | |
| let content = NSMutableAttributedString(attributedString: self.content) | |
| content.replaceFont(with: font) | |
| textView.attributedText = content | |
| if self.lineBreakMode != .byWordWrapping { | |
| textView.textContainer.maximumNumberOfLines = Int(self.height / font.lineHeight) | |
| } | |
| } else { | |
| textView.attributedText = self.content | |
| } | |
| return textView | |
| } | |
| public func updateUIView(_ textView: UITextView, context: Context) { | |
| DispatchQueue.main.async { | |
| self.height = textView.sizeThatFits(textView.bounds.size).height | |
| } | |
| } | |
| } | |
| extension AttributedTextView { | |
| public func disableInteraction(_ disable: Bool?) -> AttributedTextView { | |
| var view = self | |
| view.disableInteraction = disable ?? false | |
| return view | |
| } | |
| public func disableContextMenuInteraction(_ disable: Bool?) -> AttributedTextView { | |
| var view = self | |
| view.disableContextMenuInteraction = disable ?? false | |
| return view | |
| } | |
| } | |
| private extension NSMutableAttributedString { | |
| func replaceFont(with font: UIFont) { | |
| beginEditing() | |
| self.enumerateAttribute(.font, in: NSRange(location: 0, length: self.length)) { (value, range, stop) in | |
| removeAttribute(.font, range: range) | |
| addAttribute(.font, value: font, range: range) | |
| } | |
| endEditing() | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment