2017-02-10 2 views
2

Я использую этот код Swift 3 - CollectionView data source did not return a valid cell ОБНОВЛЕНО ОТ Теренс ОТВЕТ: В viewDidLoad я поставилSwift 3 - NSLayoutConstraint CollectionView Присоединение к другой точке зрения

collectionView?.translatesAutoresizingMaskIntoConstraints = false 
messageInputContainerView.translatesAutoresizingMaskIntoConstraints = false 
view.addConstraintsWithFormat(format: "H:|-0-[v0]-0-|", views: messageInputContainerView) 
view.addConstraintsWithFormat(format: "H:|-0-[v0]-0-|", views: collectionView!) 
let constraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[v1]-0-[v0(48)]", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":messageInputContainerView, "v1": collectionView!]) 
constraints[2].identifier = "heightConstraint" 
view.addConstraints(constraints) 
bottomConstraint = NSLayoutConstraint(item: messageInputContainerView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0) 
view.addConstraint(bottomConstraint!) 

с bottomconstraint я изменить messageInputContainerView к идет вверх, когда клавиатура появляется

messageInputContainerView.addConstraintsWithFormat(format: "H:|-8-[v0(30)]-8-[v1][v2(60)]|", views: sendPicButton, inputTextView, sendTextButton) 

messageInputContainerView.addConstraintsWithFormat(format: "V:|-6-[v0]|", views: inputTextView) 
messageInputContainerView.addConstraintsWithFormat(format: "V:[v0]-6-|", views: sendTextButton) 
messageInputContainerView.addConstraintsWithFormat(format: "V:[v0]-14-|", views: sendPicButton) 
messageInputContainerView.addConstraintsWithFormat(format: "H:|[v0]|", views: topBorderView) 
messageInputContainerView.addConstraintsWithFormat(format: "V:|[v0(0.5)]", views: topBorderView) 

screen 1

на е Первый экран У меня есть пробел между последним сообщением и messageInputContainerView. Как это исправить?

screen 2

На втором экране messageInputContainerView уже по мнению коллекции

Я модифицирующих constraints[2].identifier = "heightConstraint" в методе textViewDidChange изменить положение messageInputContainerView, когда клавиатура появляется

Как исправить его быть прикрепленным, потому что теперь его над mesagess (collectionView)?

+0

Включает ли консоль вашего журнала предупреждение о конфликтах? Ну, я смущаю, что не должен ли ваш просмотр коллекции находиться над вашим представлением ввода текста? Но ваше первое ограничение противоположно. – Terence

+0

Не конфликтует. Я редактировал свой вопрос, и я добавил все ограничения вида. Да, теперь мой textInputView находится над представлением коллекции. Я хочу привязываться к коллекцииView. –

+0

Вы задали преобразование коллекции viewAutoresizingMaskIntoConstraints false? Твои лучшие четыре ограничения есть ... и, возможно, вам стоит попробовать «V: [v1] [v0 (48)]» вместо – Terence

ответ

2

Может быть, вы можете попробовать это: контейнер добавить эти "V:|-0-[collectionView]-0-[inputview(>=48)]-0-|" и "H:|-0-[collectionView]-0-|" с "H:|-0-[inputview]-0-|" где контейнер не необходимый набор автоматического изменения размера маски ложь, если ваш контейнер также не нужно. Но как просмотр коллекции, так и входное представление необходимо установить для него false, чтобы автоматические ограничения работали.

+0

view.addConstraintsWithFormat (формат: "H: | -0- [v0] -0- |", views: messageInputContainerView) view.addConstraintsWithFormat (формат: "H: | -0- [v0] -0- |", views: collectionView!) let constraints = NSLayoutConstraint.constraints (withVisualFormat: "V: | -0- [v1] -0- [v0 (> = 48)] - 0- |", options: NSLayoutFormatOptions(), metrics: ноль, просмотров: [ "v0": messageInputContainerView, "v1": CollectionView]) CollectionView .translatesAutoresizingMaskIntoConstraints = ложные inputTextView.translatesAutoresizingMaskIntoConstraints = false' не работает, как это я получаю белый взгляд –

+0

Проверьте рамку из них? два вида после просмотра, а также контейнер, чтобы убедиться, что они правильно размещены. – Terence

+0

(0.0, 0.0, 375.0, 0.0) коллекция (46,0, 6,0, 269,0, 100,0) вход , и я не могу видеть представление коллекции inputtextView застрял в нижней части окна –

1

Одним из подходов было бы изменение ChatLogController из подкласса UICollectionViewController на простой UIViewController, а затем добавление CollectionView в качестве подчиненного объекта, добавление MessageInputContainerView в качестве подзаголовка, а затем привязка нижней части представления коллекции к началу представления ввода.

Это измененная версия класса ChatLogViewController.swift ... это из кода на шаге 7 (https://www.letsbuildthatapp.com/course_video?id=152) этого примера приложения. Вы должны быть в состоянии бросить его в свой проект в значительной степени как есть ... просто изменить загрузочную линию от:

let controller = ChatLogController(collectionViewLayout: layout) 

в

let controller = MyChatLogController() 

Также обратите внимание: это не имеет переменную -height textfield ... но если вы реализуете его так же, как и в своей версии, он должен работать очень хорошо (помните, что нижняя часть представления коллекции теперь будет «закреплена» в верхней части окна «Входной контейнер»).

Редактировать: Я сделал несколько изменений с момента моего первоначального сообщения - теперь это поддерживает поле ввода с автоматической регулировкой высоты.

import UIKit 

class MyChatLogController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UITextViewDelegate { 

    fileprivate var collectionView: UICollectionView? 

    fileprivate let cellId = "cellId" 

    var friend: Friend? { 
     didSet { 
      navigationItem.title = friend?.name 

      messages = friend?.messages?.allObjects as? [Message] 

      messages = messages?.sorted(by: {$0.date!.compare($1.date! as Date) == .orderedAscending}) 
     } 
    } 

    var messages: [Message]? 

    let messageInputContainerView: UIView = { 
     let view = UIView() 
     view.backgroundColor = UIColor.white 
     return view 
    }() 

    let inputTextView: UITextView = { 
     let textView = UITextView() 
     textView.font = UIFont.systemFont(ofSize: 18) 
     return textView 
    }() 

    let sendButton: UIButton = { 
     let button = UIButton(type: .system) 
     button.setTitle("Send", for: UIControlState()) 
     let titleColor = UIColor(red: 0, green: 137/255, blue: 249/255, alpha: 1) 
     button.setTitleColor(titleColor, for: UIControlState()) 
     button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16) 
     return button 
    }() 

    var bottomConstraint: NSLayoutConstraint? 
    var heightConstraint: NSLayoutConstraint? 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     tabBarController?.tabBar.isHidden = true 

     let layout = UICollectionViewFlowLayout() 

     collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout) 

     // make sure collectionView creation was successful 
     guard let cv = collectionView else { 
      return 
     } 

     cv.delegate = self 
     cv.dataSource = self 
     cv.translatesAutoresizingMaskIntoConstraints = false 

     cv.backgroundColor = UIColor.white 

     view.addSubview(cv) 

     cv.register(MyChatLogMessageCell.self, forCellWithReuseIdentifier: cellId) 

     view.addSubview(messageInputContainerView) 
     view.addConstraintsWithFormat("H:|[v0]|", views: messageInputContainerView) 
     view.addConstraintsWithFormat("H:|[v0]|", views: cv) 
     view.addConstraintsWithFormat("V:|[v0]-(-32)-[v1]", views: cv, messageInputContainerView) 

     bottomConstraint = NSLayoutConstraint(item: messageInputContainerView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0) 
     view.addConstraint(bottomConstraint!) 

     heightConstraint = NSLayoutConstraint(item: messageInputContainerView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 60) 
     view.addConstraint(heightConstraint!) 

     setupInputComponents() 

     inputTextView.delegate = self 
     inputTextView.isScrollEnabled = false 

     NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillShow, object: nil) 

     NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillHide, object: nil) 
    } 

    override func viewDidAppear(_ animated: Bool) { 
     super.viewDidAppear(animated) 
     let indexPath = IndexPath(item: self.messages!.count - 1, section: 0) 
     self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true) 
    } 

    func handleKeyboardNotification(_ notification: Notification) { 

     if let userInfo = notification.userInfo { 

      let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue 

      let isKeyboardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow 

      bottomConstraint?.constant = isKeyboardShowing ? -keyboardFrame!.height : 0 

      UIView.animate(withDuration: 0, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: { 

       self.view.layoutIfNeeded() 

      }, completion: { (completed) in 

       if isKeyboardShowing { 
        let indexPath = IndexPath(item: self.messages!.count - 1, section: 0) 
        self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true) 
       } 

      }) 
     } 
    } 

    func textViewDidChange(_ textView: UITextView) { //Handle the text changes here 

     let sz = textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: CGFloat.greatestFiniteMagnitude)) 

     heightConstraint?.constant = max(60, sz.height) 

     UIView.animate(withDuration: 0, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: { 

      self.view.layoutIfNeeded() 

     }, completion: { (completed) in 

      let indexPath = IndexPath(item: self.messages!.count - 1, section: 0) 
      self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true) 

     }) 

    } 

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 
     inputTextView.endEditing(true) 
    } 

    fileprivate func setupInputComponents() { 
     let topBorderView = UIView() 
     topBorderView.backgroundColor = UIColor(white: 0.75, alpha: 1.0) 

     messageInputContainerView.addSubview(inputTextView) 

     messageInputContainerView.addSubview(sendButton) 
     messageInputContainerView.addSubview(topBorderView) 

     messageInputContainerView.addConstraintsWithFormat("H:|-8-[v0][v1(60)]|", views: inputTextView, sendButton) 
     messageInputContainerView.addConstraintsWithFormat("V:|[v0]|", views: inputTextView) 

     messageInputContainerView.addConstraintsWithFormat("V:|[v0]|", views: sendButton) 

     messageInputContainerView.addConstraintsWithFormat("H:|[v0]|", views: topBorderView) 
     messageInputContainerView.addConstraintsWithFormat("V:|[v0(0.5)]", views: topBorderView) 
    } 

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     if let count = messages?.count { 
      return count 
     } 
     return 0 
    } 

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! MyChatLogMessageCell 

     cell.messageTextView.text = messages?[indexPath.item].text 

     if let message = messages?[indexPath.item], let messageText = message.text, let profileImageName = message.friend?.profileImageName { 

      cell.profileImageView.image = UIImage(named: profileImageName) 

      let size = CGSize(width: 250, height: 1000) 
      let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin) 
      let estimatedFrame = NSString(string: messageText).boundingRect(with: size, options: options, attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 18)], context: nil) 

      if message.isSender == nil || !message.isSender!.boolValue { 
       cell.messageTextView.frame = CGRect(x: 48 + 8, y: 0, width: estimatedFrame.width + 16, height: estimatedFrame.height + 20) 

       cell.textBubbleView.frame = CGRect(x: 48 - 10, y: -4, width: estimatedFrame.width + 16 + 8 + 16, height: estimatedFrame.height + 20 + 6) 

       cell.profileImageView.isHidden = false 

       //    cell.textBubbleView.backgroundColor = UIColor(white: 0.95, alpha: 1) 
       cell.bubbleImageView.image = MyChatLogMessageCell.grayBubbleImage 
       cell.bubbleImageView.tintColor = UIColor(white: 0.95, alpha: 1) 
       cell.messageTextView.textColor = UIColor.black 

      } else { 

       //outgoing sending message 

       cell.messageTextView.frame = CGRect(x: view.frame.width - estimatedFrame.width - 16 - 16 - 8, y: 0, width: estimatedFrame.width + 16, height: estimatedFrame.height + 20) 

       cell.textBubbleView.frame = CGRect(x: view.frame.width - estimatedFrame.width - 16 - 8 - 16 - 10, y: -4, width: estimatedFrame.width + 16 + 8 + 10, height: estimatedFrame.height + 20 + 6) 

       cell.profileImageView.isHidden = true 

       //    cell.textBubbleView.backgroundColor = UIColor(red: 0, green: 137/255, blue: 249/255, alpha: 1) 
       cell.bubbleImageView.image = MyChatLogMessageCell.blueBubbleImage 
       cell.bubbleImageView.tintColor = UIColor(red: 0, green: 137/255, blue: 249/255, alpha: 1) 
       cell.messageTextView.textColor = UIColor.white 
      } 

     } 

     return cell 
    } 

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 

     if let messageText = messages?[indexPath.item].text { 
      let size = CGSize(width: 250, height: 1000) 
      let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin) 
      let estimatedFrame = NSString(string: messageText).boundingRect(with: size, options: options, attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 18)], context: nil) 

      return CGSize(width: view.frame.width, height: estimatedFrame.height + 20) 
     } 

     return CGSize(width: view.frame.width, height: 100) 
    } 

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { 
     return UIEdgeInsetsMake(8, 0, 0, 0) 
    } 

} 

class MyChatLogMessageCell: BaseCell { 

    let messageTextView: UITextView = { 
     let textView = UITextView() 
     textView.font = UIFont.systemFont(ofSize: 18) 
     textView.text = "Sample message" 
     textView.backgroundColor = UIColor.clear 
     return textView 
    }() 

    let textBubbleView: UIView = { 
     let view = UIView() 
     view.layer.cornerRadius = 15 
     view.layer.masksToBounds = true 
     return view 
    }() 

    let profileImageView: UIImageView = { 
     let imageView = UIImageView() 
     imageView.contentMode = .scaleAspectFill 
     imageView.layer.cornerRadius = 15 
     imageView.layer.masksToBounds = true 
     return imageView 
    }() 

    static let grayBubbleImage = UIImage(named: "bubble_gray")!.resizableImage(withCapInsets: UIEdgeInsetsMake(22, 26, 22, 26)).withRenderingMode(.alwaysTemplate) 
    static let blueBubbleImage = UIImage(named: "bubble_blue")!.resizableImage(withCapInsets: UIEdgeInsetsMake(22, 26, 22, 26)).withRenderingMode(.alwaysTemplate) 

    let bubbleImageView: UIImageView = { 
     let imageView = UIImageView() 
     imageView.image = MyChatLogMessageCell.grayBubbleImage 
     imageView.tintColor = UIColor(white: 0.90, alpha: 1) 
     return imageView 
    }() 

    override func setupViews() { 
     super.setupViews() 

     addSubview(textBubbleView) 
     addSubview(messageTextView) 

     addSubview(profileImageView) 
     addConstraintsWithFormat("H:|-8-[v0(30)]", views: profileImageView) 
     addConstraintsWithFormat("V:[v0(30)]|", views: profileImageView) 
     profileImageView.backgroundColor = UIColor.red 

     textBubbleView.addSubview(bubbleImageView) 
     textBubbleView.addConstraintsWithFormat("H:|[v0]|", views: bubbleImageView) 
     textBubbleView.addConstraintsWithFormat("V:|[v0]|", views: bubbleImageView) 
    } 

} 
+0

Редактировать примечание - этот пример теперь включает автонастраивающийся многострочный ввод текста. – DonMag

Смежные вопросы