Изменение размера входа в AccessViewView динамически в iOS 8
В основном я пытаюсь создать изменение размера UITextView в свойстве inputAccessoryView.
У меня есть viewController с методом canBecomeFirstResponder, возвращающим true, и представление, которое я создаю через пользовательский класс (который получает его из XIB). В этом представлении находится UITextView.
Я пытаюсь изменить размер inputAccessoryView изнутри этого класса. Я попробовал несколько способов: установив рамку directy, попробуйте использовать ограничение по высоте. Кажется, он изменяется только наполовину:
Это в основном то, что я хочу (с автозапуском или без него, но работающий в iOS 7/8 +):
class MessageInputAccessory: UIView, UITextViewDelegate
{
@IBOutlet weak var textView: UITextView!
func textViewDidChange(textView: UITextView)
{
var contentSize = textView.sizeThatFits(CGSizeMake(textView.frame.size.width, CGFloat.max))
self.frame.size.height = contentSize.height + 20
self.textView.reloadInputViews()
}
}
Я нашел этот пост: Изменение фрейма inputAccessoryView в iOS 8. Заявляя, что создается автоматически созданное ограничение. Дело в том, что это не создает ограничения для меня. Ни в коем случае, если автозапуск отключен или включен (также через setTranslatesAutoresizingMaskIntoConstraints()).
Ответы
Ответ 1
Он работает для меня в iOS7/iOS8:
class MessageInputAccessory: UIView, UITextViewDelegate {
private var textView: UITextView!
private var heightConstraint: NSLayoutConstraint?
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() {
self.userInteractionEnabled = true
textView = UITextView()
textView.delegate = self
textView.bounces = false
textView.scrollEnabled = false
textView.layer.cornerRadius = 5
textView.layer.borderWidth = 1
textView.layer.borderColor = UIColor.blueColor().CGColor
self.addSubview(textView)
}
override func layoutSubviews() {
super.layoutSubviews()
textView.frame = self.bounds
}
override func addConstraint(constraint: NSLayoutConstraint) {
self.heightConstraint = constraint
super.addConstraint(constraint)
}
func textViewDidChange(textView: UITextView) {
var contentSize = textView.sizeThatFits(CGSizeMake(textView.frame.size.width, CGFloat.max))
self.frame.size.height = contentSize.height
if let heightConstraint = self.heightConstraint {
heightConstraint.constant = self.frame.size.height
}
self.textView.reloadInputViews()
}
}
EDIT: Это работает с xib тоже (iOS7/iOS8):
class MessageInputAccessory: UIView, UITextViewDelegate {
@IBOutlet var textView: UITextView!
@IBOutlet var textViewHeightConstraint: NSLayoutConstraint!
private var heightConstraint: NSLayoutConstraint?
override func awakeFromNib() {
textView.layer.cornerRadius = 5
textView.layer.borderWidth = 1
textView.layer.borderColor = UIColor.blueColor().CGColor
}
override func layoutSubviews() {
textViewHeightConstraint.constant = self.bounds.size.height
super.layoutSubviews()
}
override func addConstraint(constraint: NSLayoutConstraint) {
if constraint.firstItem === self {
self.heightConstraint = constraint
}
super.addConstraint(constraint)
}
override func addConstraints(constraints: [AnyObject]) {
super.addConstraints(constraints)
}
func textViewDidChange(textView: UITextView) {
var contentSize = textView.sizeThatFits(CGSizeMake(textView.frame.size.width, CGFloat.max))
self.frame.size.height = contentSize.height
if let heightConstraint = self.heightConstraint {
heightConstraint.constant = self.frame.size.height
}
self.textView.reloadInputViews()
}
override func intrinsicContentSize() -> CGSize {
return self.bounds.size;
}
}
Есть мой xib:
![enter image description here]()
Это не очень хорошее решение, но оно работает.. Скажите, пожалуйста, если вы знаете лучший способ.
Ответ 2
SWIFT 5 Решение
Если кто-то пытался найти решение в stackoverflow, как я, для представления входных аксессуаров, я сделал простую демонстрационную версию проекта для динамически изменяемого входного аксессуара с UITextView. Он также поставляется с нажимной кнопкой в верхней части UITextView, чтобы продемонстрировать добавленные виды в верхней части представления аксессуара ввода. Все они загружаются в XIB для легкой настройки. Написано в Swift 5, а также заботится о безопасной зоне для устройств X.
class InputAccessoryView: UIView, UITextViewDelegate {
@IBOutlet weak var textView: UITextView!
@IBOutlet weak var accessoryButtonViewHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var accessoryButtonView: UIView!
// MARK: - Init
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
}
private func setup() {
let view = self.viewFromNibForClass()
view?.frame = self.bounds
view?.autoresizingMask = [.flexibleHeight, .flexibleWidth]
self.accessoryButtonViewHeightConstraint.constant = 0
if let view = view {
self.addSubview(view)
self.textView.translatesAutoresizingMaskIntoConstraints = false
}
}
override func didMoveToWindow() {
super.didMoveToWindow()
if let window = self.window {
self.bottomAnchor.constraint(lessThanOrEqualTo: window.safeAreaLayoutGuide.bottomAnchor).isActive = true
}
}
private func viewFromNibForClass() -> UIView? {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil).first as? UIView
return view
}
func textViewDidChange(_ textView: UITextView) {
self.accessoryButtonViewHeightConstraint.constant = 40
self.accessoryButtonView.alpha = 1
self.updateHeight(textView.contentSize.height + 20 + self.accessoryButtonViewHeightConstraint.constant)
}
private func updateHeight(_ height: CGFloat) {
for constraint in self.constraints where constraint.firstAttribute == .height {
constraint.constant = height
}
}
@IBAction func accessoryButtonTouchUpInside(_ sender: Any) {
let height = self.frame.size.height - 40
self.updateHeight(height)
self.accessoryButtonViewHeightConstraint.constant = 0
}
}
Вот пример использования: https://github.com/jaysalvador/InputAccessoryView
Ответ 3
Достаточно простое исправление для этого состоит в том, чтобы не изменять фактическое изменение размера inputAccessoryView - если вы знаете максимальную высоту, которая вам понадобится для этого, вы можете создать его на максимальной высоте, сделать его прозрачным и добавить subview который изменяет размеры, как вам нравится.
Детали, необходимые для его работы, это то, что inputAccessoryView должен быть подклассом UIView, содержащим следующее:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
point = [self.innerView convertPoint:point fromView:self];
return [self.innerView pointInside:point withEvent:event];
}
(где self.innerView - это ваше динамическое изменение размера).
Это заставляет его требовать отступы внутри подвью, но передавать все, что выходит за его пределы.
Основной недостаток, о котором следует помнить, заключается в том, что уведомления о клавиатуре предоставят вам фреймы, содержащие весь входной файл max-height inputAccessoryView. Поэтому, если вы используете их (например, настраиваете вставки), вам нужно сделать дополнительную математику.