更改以编程方式创建的自定义inputAccessoryView的高度?迅速4

时间:2018-04-25 13:57:21

标签: ios swift inputaccessoryview

所以我正在创建一个消息传递应用程序,我有4个类属性:

  1. typingView: UIView!
  2. messageTextView: UITextView!
  3. sendButton: UIButton!
  4. typingViewHeight: NSLayoutConstraint?
  5. typingView是主视图的inputAccessoryView,有效!它包含messageTextViewsendButton。但我的问题是......当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 个答案:

答案 0 :(得分:0)

创建视图时,您将高度设置为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

这使您无法每次编写额外的代码行

答案 1 :(得分:0)

首先要做的事情

我建议您使用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

如果没有用,请看一下答案: https://stackoverflow.com/a/27522511/5147552