Created
August 30, 2021 17:36
-
-
Save ngeri/0080d429a0b6d195eeff3f54dafb0c11 to your computer and use it in GitHub Desktop.
Unexpected default kerning when using attributedText of UITextField
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 | |
final class ViewController: UIViewController { | |
private lazy var textField: UITextField = { | |
let view = UITextField() | |
view.translatesAutoresizingMaskIntoConstraints = false | |
view.delegate = self | |
view.borderStyle = .roundedRect | |
view.keyboardType = .numberPad | |
return view | |
}() | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
title = "Attributed UITextField" | |
view.backgroundColor = .black | |
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(backgroundTap))) | |
view.addSubview(textField) | |
NSLayoutConstraint.activate([ | |
textField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8), | |
textField.centerYAnchor.constraint(equalTo: view.centerYAnchor), | |
textField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -8) | |
]) | |
} | |
@objc func backgroundTap() { | |
textField.resignFirstResponder() | |
} | |
} | |
extension ViewController: UITextFieldDelegate { | |
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { | |
let cursorLocation = textField.position(from: textField.beginningOfDocument, offset: range.location + string.count) | |
guard let text = textField.text, let range = Range(range, in: text) else { return false } | |
let newText = text.replacingCharacters(in: range, with: string) | |
textField.attributedText = addKerning(to: .init(string: newText)) | |
if let cursorLocation = cursorLocation { | |
textField.selectedTextRange = textField.textRange(from: cursorLocation, to: cursorLocation) | |
} | |
return false | |
} | |
// func textFieldShouldReturn(_ textField: UITextField) -> Bool { | |
// textField.selectedTextRange = nil | |
// return true | |
// } | |
} | |
extension ViewController { | |
func addKerning(to string: NSAttributedString) -> NSAttributedString { | |
let groupSize = 3 | |
let kernSize: CGFloat = 4 | |
guard string.length > groupSize else { | |
return string | |
} | |
let attributedString = NSMutableAttributedString(attributedString: string) | |
for index in stride(from: string.length - 1 - groupSize, through: 0, by: -groupSize) { | |
attributedString.addAttribute(.kern, value: kernSize, range: NSRange(location: index, length: 1)) | |
} | |
return attributedString | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment