Skip to content

Instantly share code, notes, and snippets.

@spencerwhyte
Created October 4, 2018 17:30
Show Gist options
  • Save spencerwhyte/3ec7581e9b1de60e2fea1e4534b9d894 to your computer and use it in GitHub Desktop.
Save spencerwhyte/3ec7581e9b1de60e2fea1e4534b9d894 to your computer and use it in GitHub Desktop.
Another feable attempt at trying to make a performant UITextView -- just not worth the trouble
class FloatingTextView: UIControl, UITextViewDelegate {
var label: String? {
didSet {
floatingLabel.text = label
hintLabel.text = label
}
}
var text: String? {
didSet {
updateLabelVisibility()
textLabel.text = text
}
}
var floatingLabelColor: UIColor = UIColor.lightGray
var proxyInputAccessoryView: UIView?
weak var proxyTextViewDelegate: UITextViewDelegate?
private let floatingLabelPadding: CGFloat = 20
private let floatingLabel: UILabel
private let hintLabel: UILabel
private let textLabel: UILabel
private var textView: UITextView?
private var lastHideFloatingLabel: Bool? = nil
init() {
floatingLabel = UILabel()
hintLabel = UILabel()
textLabel = UILabel()
super.init(frame: CGRect.zero)
setup()
setupConstraints()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func textViewDidChange(_ textView: UITextView) {
text = textView.text
updateLabelVisibility()
proxyTextViewDelegate?.textViewDidChange?(textView)
}
@objc func startEditing() {
setupTextView()
floatingLabel.textColor = floatingLabelColor
textLabel.isHidden = true
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
self.textView?.becomeFirstResponder()
}
}
func stopEditing() {
textView?.resignFirstResponder()
textView?.removeFromSuperview()
textView = nil
floatingLabel.textColor = UIColor.lightGray
textLabel.isHidden = false
}
private func updateLabelVisibility() {
let hideFloatingLabel = text?.count == 0 || text == nil
updateOpacity(hideFloatingLabel: hideFloatingLabel)
}
private func updateOpacity(hideFloatingLabel: Bool) {
floatingLabel.isHidden = hideFloatingLabel
hintLabel.isHidden = !hideFloatingLabel
}
private func setup() {
addTarget(self, action: #selector(startEditing), for: .touchUpInside)
setupFloatingLabel()
setupHintLabel()
setupTextLabel()
updateLabelVisibility()
}
private func setupTextView() {
let textView = UITextView(frame: CGRect.zero, textContainer: nil)
self.textView = textView
textView.translatesAutoresizingMaskIntoConstraints = false
textView.text = text
textView.isScrollEnabled = false
textView.font = UIFont.systemFont(ofSize: 17)
textView.backgroundColor = UIColor.clear
textView.delegate = self
textView.backgroundColor = UIColor.clear
textView.inputAccessoryView = proxyInputAccessoryView
addSubview(textView)
NSLayoutConstraint.activate([
textView.leadingAnchor.constraint(equalTo: leadingAnchor),
textView.trailingAnchor.constraint(equalTo: textLabel.trailingAnchor),
textView.topAnchor.constraint(equalTo: floatingLabel.bottomAnchor, constant: -3.5)
])
}
private func setupTextLabel() {
textLabel.translatesAutoresizingMaskIntoConstraints = false
textLabel.font = UIFont.systemFont(ofSize: 17)
textLabel.numberOfLines = 0
addSubview(textLabel)
}
private func setupFloatingLabel() {
floatingLabel.translatesAutoresizingMaskIntoConstraints = false
floatingLabel.font = UIFont.systemFont(ofSize: 12)
floatingLabel.textColor = floatingLabelColor
addSubview(floatingLabel)
}
private func setupHintLabel() {
hintLabel.translatesAutoresizingMaskIntoConstraints = false
hintLabel.textColor = UIColor.lightGray
hintLabel.font = UIFont.systemFont(ofSize: 17)
addSubview(hintLabel)
}
private func setupConstraints() {
NSLayoutConstraint.activate([
floatingLabel.topAnchor.constraint(equalTo: topAnchor, constant: 5),
floatingLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 5),
textLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 5),
textLabel.trailingAnchor.constraint(equalTo: trailingAnchor),
textLabel.topAnchor.constraint(equalTo: floatingLabel.bottomAnchor, constant: 5),
hintLabel.leadingAnchor.constraint(equalTo: textLabel.leadingAnchor),
hintLabel.topAnchor.constraint(equalTo: textLabel.topAnchor),
hintLabel.trailingAnchor.constraint(equalTo: textLabel.trailingAnchor),
bottomAnchor.constraint(greaterThanOrEqualTo: textLabel.bottomAnchor, constant: 5),
bottomAnchor.constraint(greaterThanOrEqualTo: hintLabel.bottomAnchor, constant: 5)
])
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment