Создание входного вспомогательного представления программно - PullRequest
0 голосов
/ 02 мая 2018

Я пытаюсь создать вспомогательный вид клавиатуры программным способом. Я настроил вид контейнера, и внутри я пытаюсь настроить текстовое поле, кнопку отправки и эмодзи. Вот пример того, что я пытаюсь сделать.

Нажмите здесь, чтобы посмотреть изображение.

Вот код, с которым я работаю. Я думаю, что проблема в том, когда я устанавливаю ограничения. У меня в голове есть пара вопросов:

  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
    }
    }
    

Это ошибка, которую я продолжаю получать.

*** Завершение приложения из-за необработанного исключения «NSGenericException», причина: «Невозможно активировать ограничение с помощью якорей, и потому что у них нет общего предка. Указывает ли ограничение или его привязки на элементы в разных иерархиях представления? Это незаконно. '

EDIT

View Post Controller

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 работает: Нажмите здесь

Расширение TextView: Нажмите здесь.

1 Ответ

0 голосов
/ 02 мая 2018

Перед применением ограничений представление должно быть в иерархии представлений или ошибка, которую вы получили, будет поднята. Чтобы избавиться от ошибки, просто сделайте 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
    }
}
...