-
-
Save q231950/19d389146bcda87a7f94cee24fff15c4 to your computer and use it in GitHub Desktop.
Avoid UITextView alignment bug. https://stackoverflow.com/questions/26524431/uitextview-alignment-caret-goes-left
This file contains 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 UIKit | |
class CenteredTextView: UITextView { | |
override init(frame: CGRect, textContainer: NSTextContainer?) { | |
super.init(frame: frame, textContainer: textContainer) | |
setup() | |
} | |
required init?(coder: NSCoder) { | |
super.init(coder: coder) | |
setup() | |
} | |
override func prepareForInterfaceBuilder() { | |
super.prepareForInterfaceBuilder() | |
setup() | |
} | |
private func setup() { | |
textAlignment = .center | |
// Avoid the bug of the text align changed to the left. | |
NotificationCenter.default.addObserver(forName: UITextView.textDidChangeNotification, object: self, queue: .main) { [weak self] (_) in | |
guard self?.textAlignment != .center else { return } | |
self?.textAlignment = .center | |
} | |
} | |
// Avoid the bug of the caret position changed to the left. | |
override func caretRect(for position: UITextPosition) -> CGRect { | |
let caretRect = super.caretRect(for: position) | |
let rangeOfCaret = NSRange(location: selectedRange.location + selectedRange.length, length: 0) | |
let rangeOfCharBeforeCaret = NSRange(location: rangeOfCaret.location > 0 ? rangeOfCaret.location - 1 : 0, length: 1) | |
let rangeOfCharAfterCaret = NSRange(location: rangeOfCaret.location, length: 1) | |
let fullRange = NSRange(location: 0, length: text.length) | |
guard | |
NSLocationInRange(rangeOfCharBeforeCaret.location, fullRange), | |
NSLocationInRange(NSMaxRange(rangeOfCharAfterCaret), fullRange), | |
text.substring(with: rangeOfCharBeforeCaret) == "\n", | |
text.substring(with: rangeOfCharAfterCaret) == "\n" | |
else { return caretRect } | |
// Newline before and after the caret. Make it centered. | |
let correction = bounds.midX - caretRect.midX | |
let centeredCaretRect = caretRect.offsetBy(dx: correction, dy: 0) | |
return centeredCaretRect | |
} | |
} | |
fileprivate extension String { | |
func substring(with nsrange: NSRange) -> Substring? { | |
guard let range = Range(nsrange, in: self) else { return nil } | |
return self[range] | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment