Last active
August 17, 2020 06:32
-
-
Save wata/bf7112fe46959ff18f9356137407f985 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
Hey, This code doesn't work like
text\n
->text(new \n)\n
Check here,
https://gist.github.com/Haeuncs/197e8dc11fad49528ed638526cc7beca
If there is a problem with the code I modified, please let me know. 😮