Изменить высоту программно созданного пользовательского inputAccessoryView? Свифт 4
Итак, я делаю приложение для обмена сообщениями, и у меня есть 4 свойства класса:
typingView: UIView!
messageTextView: UITextView!
sendButton: UIButton!
typingViewHeight: NSLayoutConstraint?
typingView
это inputAccessoryView
основного вида, который работает! Он содержит messageTextView
а также sendButton
, Но моя проблема... когда количество строк текста в messageTextView
увеличивается, я хочу, чтобы высота увеличивалась с анимацией (сейчас я игнорирую уменьшение). И, сделав это, я решил изменить высоту typingView
,
Обнаружение изменений в contentSize работает отлично, я добавил наблюдателя, добавив эту строку
messageTextView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
и слушал это с этим переопределением
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
Внутри этой функции у меня есть (это чрезмерное упрощение и псевдокод, только предположим, что это работает)
UIView.animate(withDuration: keyboardAnimationDuration) {
self.typingViewHeight?.constaint += (messageTextView.font?.lineHeight)!
}
Вот мой код для настройки inputAccessoryView
:
lazy var typingViewContainer: UIView = {
// Set up typing view
typingView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 55))
typingView.backgroundColor = UIColor.darkGray
typingView.translatesAutoresizingMaskIntoConstraints = false
// Set up animated constraints
typingViewHeight = typingView.heightAnchor.constraint(equalToConstant: typingView.frame.height)
typingViewHeight?.isActive = true
// Set up text view
messageTextView = UITextView()
messageTextView.translatesAutoresizingMaskIntoConstraints = false
messageTextView.font = fakeMessageTextView.font
messageTextView.keyboardType = fakeMessageTextView.keyboardType
messageTextView.isScrollEnabled = fakeMessageTextView.isScrollEnabled
messageTextView.alwaysBounceVertical = fakeMessageTextView.alwaysBounceVertical
messageTextView.text = fakeMessageTextView.text
messageTextView.textColor = fakeMessageTextView.textColor
messageTextView.delegate = self
typingView.addSubview(messageTextView)
// Constraints
messageTextView.bottomAnchor.constraint(equalTo: typingView.bottomAnchor, constant: -fakeMessageTextViewBottom.constant).isActive = true
messageTextView.topAnchor.constraint(equalTo: typingView.topAnchor, constant: fakeMessageTextViewTop.constant).isActive = true
messageTextView.leftAnchor.constraint(equalTo: typingView.leftAnchor, constant: fakeMessageTextViewBottom.constant).isActive = true
messageTextView.widthAnchor.constraint(equalToConstant: fakeMessageTextViewWidth.constant).isActive = true
// Observers
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
messageTextView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
// Set up send button
sendButton = UIButton(type: fakeSendButton.buttonType)
sendButton.translatesAutoresizingMaskIntoConstraints = false
sendButton.setTitle(fakeSendButton.titleLabel?.text!, for: .normal)
sendButton.titleLabel?.font = fakeSendButton.titleLabel?.font
sendButton.titleLabel?.shadowColor = fakeSendButton.titleLabel?.shadowColor
sendButton.addTarget(self, action: #selector(sendPressed(_:)), for: .touchUpInside)
typingView.addSubview(sendButton)
// Constraints
sendButton.heightAnchor.constraint(equalToConstant: fakeSendButtonHeight.constant).isActive = true
sendButton.widthAnchor.constraint(equalToConstant: fakeSendButtonWidth.constant).isActive = true
sendButton.bottomAnchor.constraint(equalTo: typingView.bottomAnchor, constant: -fakeSendButtonBottom.constant).isActive = true
sendButton.rightAnchor.constraint(equalTo: typingView.rightAnchor, constant: -fakeSendButtonRight.constant).isActive = true
return typingView
}()
override var inputAccessoryView: UIView? {
get {
return typingViewContainer
}
}
override var canBecomeFirstResponder: Bool {
get {
return true
}
}
Но когда я проверяю это и набираю несколько строк, он выводит это на консоль:
2018-04-25 08:52:57.614383-0500 ProxiChat[3351:168967] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x608000280a50 UIView:0x7f8528a2cda0.height == 73 (active)>",
"<NSLayoutConstraint:0x6040000993c0 UIView:0x7f8528a2cda0.height == 55 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x608000280a50 UIView:0x7f8528a2cda0.height == 73
(active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
Почему есть два ограничения? Я только добавил один. Пожалуйста, помогите, спасибо!
РЕДАКТИРОВАТЬ
Предположим, что мой код для изменения высоты typingView
работает, поскольку он работал до того, как я изменил свое представление на пользовательский inputAccessoryView. Я просто хочу знать, почему она печатает эту ошибку, и как я могу исправить ее, установив два ограничения, хотя я только добавил одно?
2 ответа
Когда вы создаете вид, вы устанавливаете высоту 55:
typingView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 55))
И тогда вы устанавливаете якорь высоты:
typingViewHeight = typingView.heightAnchor.constraint(equalToConstant: typingView.frame.height)
typingViewHeight?.isActive = true
Вот почему вы видите конфликт. Другое наблюдение заключается в том, что при установке привязки высоты вы можете активировать ее в той же строке, в которой он создан:
typingViewHeight = typingView.heightAnchor.constraint(equalToConstant: typingView.frame.height).isActive = true
Это удерживает вас от написания дополнительной строки кода каждый раз
Перво-наперво
Вместо наблюдения я рекомендую вам использовать UITextView
метод делегата для регулировки высоты контейнера и вашего текстового представления. Этот код делает то же самое, но я думаю, что он более лаконичен и чист.
func textViewDidChange(_ textView: UITextView) {
let sizeToFitIn = CGSize(width: textView.bounds.size.width, height: .greatestFiniteMagnitude)
let newSize = textView.sizeThatFits(sizeToFitIn)
var newHeight = newSize.height
....
// That part depends on your approach to placing constraints, it's just my example
textInputHeightConstraint?.constant = newHeight
inputContainerHeightConstraint?.constant = newHeight + (interfaceFactory.inputContainerHeight - interfaceFactory.textInputMinimumHeight)
}
Попробуйте обновить ваш код так:
typingViewHeight = typingView.heightAnchor.constraint(equalToConstant: typingView.frame.height)
typingViewHeight?.priority = UILayoutPriority(rawValue: 999)
typingViewHeight?.isActive = true
Если это не поможет, взгляните на этот ответ: /questions/25299074/izmenit-vyisotu-problemyi-inputaccessoryview/25299076#25299076