以编程方式创建输入附件视图

时间:2018-05-02 18:41:32

标签: ios swift ios-autolayout

我试图以编程方式创建键盘配件视图。我已经设置了一个容器视图,在里面我尝试设置文本字段,发布按钮和表情符号。 这是我尝试制作的一个例子。

Click here to view the image.

这是我正在使用的代码。我认为问题在于我设置约束。 在我脑海中浮现的几个问题是:

  1. 我是否需要为容器视图设置约束?

  2. 如何在文本字段中添加适当的约束?

    override var inputAccessoryView: UIView? {
    get {
        //Set up the container
        let containerView = UIView()
        containerView.backgroundColor = #colorLiteral(red: 0.9784782529, green: 0.9650371671, blue: 0.9372026324, alpha: 1)
        containerView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 60)
    
        let textField = UITextField()
        textField.placeholder = "Add a reframe..."
        textField.isSecureTextEntry = false
        textField.textAlignment = .left
        textField.borderStyle = .none
        textField.translatesAutoresizingMaskIntoConstraints = false
    
    
        textField.translatesAutoresizingMaskIntoConstraints = false
        textField.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true
        textField.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true
        textField.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true
        textField.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true
        textField.heightAnchor.constraint(equalToConstant: 50)
    
    
        containerView.addSubview(textField)
    
        return containerView
    }
    }
    
  3. 这是我一直在犯的错误。

    ***由于未捕获的异常终止应用程序' NSGenericException',原因:'无法使用锚点激活约束,因为它们没有共同的祖先。约束或其锚点是否引用不同视图层次结构中的项目?这是非法的。'

    修改

    查看帖子控制器

    lazy var containerView: CommentInputAccessoryView = {
        let frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 60)
        let commentInputAccessoryView = CommentInputAccessoryView(frame: frame)
        commentInputAccessoryView.delegate = self
        return commentInputAccessoryView
    }()
    
    //Setting up the keyboard accessory view for comments.
    override var inputAccessoryView: UIView? {
        get {
            return containerView
        }
    }
    override var canBecomeFirstResponder: Bool {
        return true
    }
    

    CommentInputAccessoryView

    protocol CommentInputAccessoryViewDelegate {
    func didSend(for comment: String)
    }
    
    class CommentInputAccessoryView: UIView {
    
    var delegate: CommentInputAccessoryViewDelegate?
    
    func clearCommentTextView() {
        commentTextView.text = nil
        showPlaceholderLabel()
    }
    
    let commentTextView: UITextView = {
        let text = UITextView()
        text.translatesAutoresizingMaskIntoConstraints = false
        //text.placeholder = "Add a reframe..."
        text.textAlignment = .left
        text.backgroundColor = #colorLiteral(red: 0.9784782529, green: 0.9650371671, blue: 0.9372026324, alpha: 1)
        text.layer.cornerRadius = 50/2
        text.layer.masksToBounds = true
        text.isScrollEnabled = false
        text.font = UIFont.systemFont(ofSize: 16)
        text.textContainerInset = UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 64)
        //text.borderStyle = .none
        return text
    }()
    
    let placeholderLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "Add a response..."
        label.textColor = .black
        label.font = UIFont.systemFont(ofSize: 16)
        return label
    }()
    
    func showPlaceholderLabel() {
        placeholderLabel.isHidden = false
    }
    
    let sendButton: UIButton = {
        let send = UIButton(type: .system)
        //let sendButton = UIImageView(image: #imageLiteral(resourceName: "arrowUp"))
        send.translatesAutoresizingMaskIntoConstraints = false
        send.setTitle("Send", for: .normal)
        send.setTitleColor(#colorLiteral(red: 0.2901960784, green: 0.3725490196, blue: 0.937254902, alpha: 1), for: .normal)
        send.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 10)
        send.addTarget(self, action: #selector(handlePostComment), for: .touchUpInside)
        return send
    }()
    
    let hugButton: UIButton = {
        let hug = UIButton()
        hug.translatesAutoresizingMaskIntoConstraints = false
        hug.setTitle("", for: .normal)
        hug.backgroundColor = #colorLiteral(red: 0.9784782529, green: 0.9650371671, blue: 0.9372026324, alpha: 1)
        hug.contentEdgeInsets = UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12)
        hug.layer.cornerRadius = 25
        hug.layer.masksToBounds = true
        return hug
    }()
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        autoresizingMask = .flexibleHeight
    
        addSubview(commentTextView)
        addSubview(sendButton)
        addSubview(hugButton)
        addSubview(placeholderLabel)
    
    
        if #available(iOS 11.0, *) {
            commentTextView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -10).isActive = true
            hugButton.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -10).isActive = true
        }
        else {
        }
    
        commentTextView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor, constant: 8).isActive = true
        commentTextView.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
        commentTextView.trailingAnchor.constraint(equalTo: hugButton.leadingAnchor, constant: 8)
    
        placeholderLabel.leadingAnchor.constraint(equalTo: commentTextView.leadingAnchor, constant: 18).isActive = true
        placeholderLabel.centerYAnchor.constraint(equalTo: self.commentTextView.centerYAnchor).isActive = true
    
        sendButton.trailingAnchor.constraint(equalTo: self.commentTextView.trailingAnchor, constant: -10).isActive = true
        sendButton.centerYAnchor.constraint(equalTo: self.commentTextView.bottomAnchor, constant: -22).isActive = true
    
        hugButton.leadingAnchor.constraint(equalTo: self.commentTextView.trailingAnchor, constant: 10).isActive = true
        hugButton.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -8).isActive = true
        hugButton.widthAnchor.constraint(equalToConstant: 40)
        //hugButton.centerYAnchor.constraint(equalTo: self.commentTextView.centerYAnchor).isActive = true
    
        NotificationCenter.default.addObserver(self, selector: #selector(handleTextChanged), name: .UITextViewTextDidChange, object: nil)
    }
    
    override var intrinsicContentSize: CGSize {
        return .zero
    }
    
    @objc func handleTextChanged() {
        placeholderLabel.isHidden = !self.commentTextView.text.isEmpty
    }
    
    @objc func handlePostComment() {
        guard let commentText = commentTextView.text else {return}
        delegate?.didSend(for: commentText)
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    }
    

    以下是一些可能对正在发生的事情有所帮助的照片。

    InputAccessoryView工作: Click here

    TextView扩展: Click here.

1 个答案:

答案 0 :(得分:0)

在应用约束之前,视图应该在视图层次结构中,否则将引发错误。要摆脱错误,请在containerView.addSubview(textField)后执行let textField = UITextField()

关于您发布的示例图片,初始解决方案可能是这样的

override var inputAccessoryView: UIView? {
    get {
        //Set up the container
        let containerView = UIView()
        containerView.backgroundColor = #colorLiteral(red: 0.9784782529, green: 0.9650371671, blue: 0.9372026324, alpha: 1)
        containerView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 60)

        let textField = UITextField()
        containerView.addSubview(textField)
        textField.translatesAutoresizingMaskIntoConstraints = false
        textField.placeholder = "Add a reframe..."
        textField.textAlignment = .left
        textField.backgroundColor = .white
        textField.layer.cornerRadius = 50/2
        textField.layer.masksToBounds = true
        textField.borderStyle = .none
        textField.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 8).isActive = true
        textField.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -5).isActive = true
        textField.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 10).isActive = true
        textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 15, height: textField.frame.height)) // adding left padding so it's not sticked to border
        textField.leftViewMode = .always

        let arrow = UIImageView(image: #imageLiteral(resourceName: "arrowUp"))
        containerView.addSubview(arrow)
        arrow.translatesAutoresizingMaskIntoConstraints = false
        arrow.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: -10).isActive = true
        arrow.centerYAnchor.constraint(equalTo: textField.centerYAnchor).isActive = true

        let button = UIButton()
        containerView.addSubview(button)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle("", for: .normal)
        button.contentEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
        button.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 10).isActive = true
        button.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -8).isActive = true
        button.centerYAnchor.constraint(equalTo: textField.centerYAnchor).isActive = true

        // Negative values for constraints can be avoided if we change order of views when applying constrains
        // f.e. instead of button.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -8).isActive = true
        // write containerView.trailingAnchor.constraint(equalTo: button.trailingAnchor, constant: 8).isActive = true

        return containerView
    }
}