Swiftgram/TelegramUI/ResizeableTextInputView.swift
2016-08-23 16:21:34 +03:00

113 lines
5.1 KiB
Swift

import Foundation
import UIKit
import Display
class ResizeableTextInputViewImpl: UITextView {
override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) {
super.setContentOffset(contentOffset, animated: false)
}
}
class ResizeableTextInputView: UIView, UITextViewDelegate {
let textView: ResizeableTextInputViewImpl
let shadowTextView: ResizeableTextInputViewImpl
let placeholderLabel: UILabel
var updateHeight: () -> Void = { }
var maxHeightForLines: CGFloat
var heightForSingleLine: CGFloat
let insets = UIEdgeInsets(top: 2.0, left: 0.0, bottom: 4.0, right: 0.0)
var placeholder: String {
get {
return self.placeholderLabel.text ?? ""
} set(value) {
self.placeholderLabel.text = value
self.placeholderLabel.sizeToFit()
let placeholderSize = self.placeholderLabel.bounds.size
self.placeholderLabel.frame = CGRect(x: 2.0, y: self.insets.top, width: placeholderSize.width, height: placeholderSize.height)
}
}
init() {
self.textView = ResizeableTextInputViewImpl()
self.textView.layoutManager.allowsNonContiguousLayout = true
self.textView.textContainerInset = UIEdgeInsets(top: 0.0, left: self.insets.left, bottom: 0.0, right: self.insets.right)
self.textView.backgroundColor = UIColor.clear
self.textView.textColor = UIColor.black
self.textView.isOpaque = false
self.textView.font = Font.regular(16.0)
self.shadowTextView = ResizeableTextInputViewImpl()
self.shadowTextView.font = self.textView.font
self.shadowTextView.textContainerInset = self.textView.textContainerInset
self.shadowTextView.layoutManager.allowsNonContiguousLayout = true
self.shadowTextView.frame = CGRect(x: 0.0, y: 0.0, width: 100.0, height: CGFloat.greatestFiniteMagnitude)
self.shadowTextView.text = "A"
self.shadowTextView.layoutManager.ensureLayout(for: shadowTextView.textContainer)
let singleLineHeight = ceil(shadowTextView.layoutManager.usedRect(for: shadowTextView.textContainer).size.height)
self.heightForSingleLine = singleLineHeight + 2.0 + self.insets.top + self.insets.bottom
self.shadowTextView.text = "\n\n\n"
self.shadowTextView.layoutManager.ensureLayout(for: shadowTextView.textContainer)
let maxHeight = ceil(shadowTextView.layoutManager.usedRect(for: shadowTextView.textContainer).size.height)
self.maxHeightForLines = maxHeight + 2.0 + self.insets.top + self.insets.bottom
self.placeholderLabel = UILabel()
super.init(frame: CGRect())
self.clipsToBounds = true
self.textView.delegate = self
self.addSubview(textView)
self.placeholderLabel.font = self.textView.font
self.placeholderLabel.textColor = UIColor(0xbebec0)
self.addSubview(self.placeholderLabel)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func maxHeight() -> CGFloat {
return self.maxHeightForLines
}
func calculateSizeThatFits(constrainedSize: CGSize) -> CGSize {
self.shadowTextView.frame = CGRect(x: 0.0, y: 0.0, width: constrainedSize.width + 4.0, height: CGFloat.greatestFiniteMagnitude)
self.shadowTextView.text = "\n"
//shadowTextView.layoutManager.ensureLayoutForTextContainer(shadowTextView.textContainer)
self.shadowTextView.text = textView.text
shadowTextView.layoutManager.glyphRange(for: shadowTextView.textContainer)
let height = ceil(shadowTextView.layoutManager.usedRect(for: shadowTextView.textContainer).size.height)
return CGSize(width: constrainedSize.width, height: min(height + 2.0 + self.insets.top + self.insets.bottom, self.maxHeight()))
}
func textViewDidChange(_ textView: UITextView) {
self.placeholderLabel.isHidden = textView.text.startIndex != textView.text.endIndex
self.updateHeight()
}
override var frame: CGRect {
get {
return super.frame
} set(value) {
super.frame = value
let heightFix: CGFloat = 25.0
self.textView.frame = CGRect(x: -4.0, y: -0.5, width: value.size.width + 4.0, height: value.size.height + heightFix - self.insets.bottom)
let distance = -(self.maxHeight() - self.textView.frame.size.height)
self.clipsToBounds = distance > 0.0
self.textView.contentInset = UIEdgeInsets(top: 2.0 + self.insets.top, left: 0.0, bottom: max(0.0, distance) + self.insets.bottom, right: 0.0)
self.textView.scrollIndicatorInsets = UIEdgeInsets(top: 2.0 + self.insets.top, left: 0.0, bottom: max(0.0, distance) + self.insets.bottom, right: -2.0)
let placeholderSize = self.placeholderLabel.bounds.size
self.placeholderLabel.frame = CGRect(x: 1.0, y: self.insets.top + 2.0, width: placeholderSize.width, height: placeholderSize.height)
}
}
}