使用新类型的Cell插入UICollectionView中的新部分

时间:2018-02-07 20:20:12

标签: ios swift swift3 uicollectionview uicollectionviewcell

我正在开发一款聊天应用。我正在使用UICollectionView来显示文本和不同类型的文本。我有3种类型的细胞。在第一部分中,我正在加载第一种类型的单元格。在第二种,第二种类型和第三种,第三种类型的细胞装载中。我有一个按钮文本字段。当我单击文本字段中的发送按钮时,我想创建第一个单元格类型的新部分。我不知道如何创作。请帮助:)

这是我的代码:

//  ChatLogController.swift
//  Blubyn
//
//  Created by JOGENDRA on 02/02/18.
//  Copyright © 2018 Jogendra Singh. All rights reserved.
//

import UIKit

fileprivate enum DefaultConstants {

    static let sendButtonImageName: String = "send-icon"
    static let voiceButtonImageName: String = "microphone"
}

enum Cells {
    case chatCell
    case oneWayFlight
    case twoWayFlight
}


class ChatLogController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

    fileprivate var sideBar = SideBar()

    lazy var inputTextField: UITextField = {
        let textField = UITextField()
        textField.placeholder = "Send a message..."
        textField.delegate = self
        return textField
    }()

    let textView: UIView = {
        let textFieldview = UIView()
        textFieldview.backgroundColor = UIColor.white
        textFieldview.translatesAutoresizingMaskIntoConstraints = false
        return textFieldview
    }()

    let cellId = "cellId"
    let oneWayCellId = "oneWayFlightCell"
    let twoWayCellId = "twoWayFlightCell"

    var numberOfSections: Int = 0
    var numberOfItemsInASection: Int = 0

    var cellType: Cells?

    var keyboardHeight: CGFloat = 0.0

    var textViewBottomAnchor: NSLayoutConstraint?

    var userMessages: [String] = ["Hey there!", "I want to book flight for Pokhara, Nepal", "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s", "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.", "Book a hotel for me near lakeside", "book returning flight"]

    var systemMessages: [String] = ["Hello Jogendra!", "Pluto at your service - your guide and concierge to help you with the planning ticket booking and finding new and exotic places.", "Go on! Try me out. Won't take long. I promise."]

    lazy var messages: [String] = systemMessages + userMessages

    override func viewDidLoad() {
        super.viewDidLoad()

        setupInputComponents()
        sideBarSetup()

        collectionView?.contentInset = UIEdgeInsets(top: 8.0, left: 0, bottom: 52.0, right: 0)
        collectionView?.backgroundColor = UIColor.chatbackgroundColor

        // Register Chat Cell
        collectionView?.register(ChatMessagesCell.self, forCellWithReuseIdentifier: cellId)

        // Regsiter One Way Flight Cell
        let oneWayFlightCellNib = UINib(nibName: "OneWayFlightViewCell", bundle: nil)
        collectionView?.register(oneWayFlightCellNib, forCellWithReuseIdentifier: oneWayCellId)

        // Register Two Way Flight Cell
        let twoWayFlightCellNib = UINib(nibName: "TwoWayFlightViewCell", bundle: nil)
        collectionView?.register(twoWayFlightCellNib, forCellWithReuseIdentifier: twoWayCellId)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(true)

        // Register Notification, To know When Key Board Appear.
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: Notification.Name.UIKeyboardWillShow, object: nil)

        // Register Notification, To know When Key Board Hides.
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(true)

        // De register the notifications
        NotificationCenter.default.removeObserver(self)
    }

    fileprivate func setupInputComponents() {

        // Text View setups
        view.addSubview(textView)
        textView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        textView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        textView.heightAnchor.constraint(equalToConstant: 44.0).isActive = true
        textViewBottomAnchor = textView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
        textViewBottomAnchor?.isActive = true

        let voiceButton = UIButton(type: .system)
        let voiceButtonImage = UIImage(named: DefaultConstants.voiceButtonImageName)
        voiceButton.setImage(voiceButtonImage, for: .normal)
        textView.addSubview(voiceButton)
        voiceButton.translatesAutoresizingMaskIntoConstraints = false
        voiceButton.topAnchor.constraint(equalTo: textView.topAnchor).isActive = true
        voiceButton.trailingAnchor.constraint(equalTo: textView.trailingAnchor).isActive = true
        voiceButton.bottomAnchor.constraint(equalTo: textView.bottomAnchor).isActive = true
        voiceButton.widthAnchor.constraint(equalToConstant: 44.0).isActive = true

        let sendButton = UIButton(type: .system)
        let sendButtonImage = UIImage(named: DefaultConstants.sendButtonImageName)
        sendButton.setImage(sendButtonImage, for: .normal)
        textView.addSubview(sendButton)
        sendButton.addTarget(self, action: #selector(didTapSend), for: .touchUpInside)
        sendButton.translatesAutoresizingMaskIntoConstraints = false
        sendButton.topAnchor.constraint(equalTo: textView.topAnchor).isActive = true
        sendButton.trailingAnchor.constraint(equalTo: voiceButton.leadingAnchor).isActive = true
        sendButton.bottomAnchor.constraint(equalTo: textView.bottomAnchor).isActive = true
        sendButton.widthAnchor.constraint(equalToConstant: 44.0).isActive = true

        textView.addSubview(inputTextField)
        inputTextField.translatesAutoresizingMaskIntoConstraints = false
        inputTextField.leadingAnchor.constraint(equalTo: textView.leadingAnchor, constant: 4.0).isActive = true
        inputTextField.trailingAnchor.constraint(equalTo: sendButton.leadingAnchor, constant: -4.0).isActive = true
        inputTextField.topAnchor.constraint(equalTo: textView.topAnchor).isActive = true
        inputTextField.bottomAnchor.constraint(equalTo: textView.safeAreaLayoutGuide.bottomAnchor).isActive = true

        let separator = UIView()
        separator.backgroundColor = UIColor.black.withAlphaComponent(0.4)
        textView.addSubview(separator)
        separator.translatesAutoresizingMaskIntoConstraints = false
        separator.leadingAnchor.constraint(equalTo: textView.leadingAnchor).isActive = true
        separator.trailingAnchor.constraint(equalTo: textView.trailingAnchor).isActive = true
        separator.topAnchor.constraint(equalTo: textView.topAnchor).isActive = true
        separator.heightAnchor.constraint(equalToConstant: 1.0).isActive = true

    }

    // MARK: - Keyboard Events

    @objc func keyboardWillShow(_ notification: Notification) {
        if let keyboardFrame: NSValue = notification.userInfo![UIKeyboardFrameEndUserInfoKey] as? NSValue {
            let keyboardRectangle = keyboardFrame.cgRectValue
            keyboardHeight = keyboardRectangle.height
        }
        let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double

        textViewBottomAnchor?.constant = -keyboardHeight
        UIView.animate(withDuration: keyboardDuration!, animations: {
            self.view.layoutIfNeeded()
        })
    }

    @objc func keyboardWillHide(_ notification: Notification) {

        let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double
        textViewBottomAnchor?.constant = 0

        UIView.animate(withDuration: keyboardDuration!, animations: {
            self.view.layoutIfNeeded()
        })

    }

    // MARK: - Collection View Methods

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        switch section {
        case 0:
            return messages.count
        case 1:
            numberOfItemsInASection = 5
            return numberOfItemsInASection
        case 2:
            return 5
        default:
            numberOfItemsInASection = 5
            return numberOfItemsInASection
        }

    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! ChatMessagesCell

        let message = messages[indexPath.item]
        cell.chatTextView.text = message

        // Align chat cell according
        if userMessages.contains(message) {

            cell.bubbleView.backgroundColor = UIColor.white
            cell.chatTextView.textColor = UIColor.black

            cell.bubbleViewRightAnchor?.isActive = true
            cell.bubbleViewLeftAnchor?.isActive = false

        } else {

            cell.bubbleView.backgroundColor = UIColor.chatThemeColor
            cell.chatTextView.textColor = UIColor.white

            cell.bubbleViewRightAnchor?.isActive = false
            cell.bubbleViewLeftAnchor?.isActive = true
        }

        //Modify the width accordingly
        cell.bubbleWidthAnchor?.constant = estimateFrameForText(text: message).width + 32.0

        if indexPath.section == 0 {
            cellType = Cells.chatCell
            return cell
        } else if indexPath.section == 1 {
            let oneWayFlightCell = collectionView.dequeueReusableCell(withReuseIdentifier: oneWayCellId, for: indexPath) as! OneWayFlightViewCell
            cellType = Cells.oneWayFlight
            return oneWayFlightCell
        } else {
            let twoWayFlightCell = collectionView.dequeueReusableCell(withReuseIdentifier: twoWayCellId, for: indexPath) as! TwoWayFlightViewCell
            cellType = Cells.twoWayFlight
            return twoWayFlightCell
        }
    }

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        numberOfSections = 3
        return numberOfSections
    }


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

        var cellHeight: CGFloat = 80.0
        let text = messages[indexPath.item]
        cellHeight = estimateFrameForText(text: text).height + 20.0

        if indexPath.section == 1 {
            cellHeight = 112
        } else if indexPath.section == 2 {
            cellHeight = 201
        }

        return CGSize(width: collectionView.frame.width, height: cellHeight)
    }

    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        inputTextField.resignFirstResponder()
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        //{top, left, bottom, right}
        return UIEdgeInsetsMake(10, 0, 10, 0)
    }

    private func estimateFrameForText(text: String) -> CGRect {
        let size = CGSize(width: 300.0, height: 1000)
        let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
        return NSString(string: text).boundingRect(with: size, options: options, attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 17.0)], context: nil)
    }

    @objc fileprivate func didTapSend() {

        if let enteredText = inputTextField.text, !enteredText.isEmpty {
            messages.append(enteredText)
            userMessages.append(enteredText)
        }
        collectionView?.reloadData()
        inputTextField.text = nil
    }

    fileprivate func sideBarSetup() {

        sideBar = SideBar(sourceView: self.view, menuItems: ["Chat", "Hot Deals", "My Trips", "Experiences", "Settings", "Profile"])
        sideBar.delegate = self
    }

    @IBAction func didTapMenu(_ sender: Any) {
        sideBar.showSideBar(!sideBar.isSideBarOpen)
    }


    @IBAction func didTapHelp(_ sender: Any) {

    }

}

extension ChatLogController: SideBarDelegate {

    func SideBarDidSelectButtonAtIndex(_ index: Int) {

        switch index {
        case 0:
            sideBar.showSideBar(!sideBar.isSideBarOpen)
        case 1:
            sideBar.showSideBar(!sideBar.isSideBarOpen)
        case 2:
            sideBar.showSideBar(!sideBar.isSideBarOpen)
        case 3:
            sideBar.showSideBar(!sideBar.isSideBarOpen)
        case 4:
            let settingStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let settingsViewController = settingStoryboard.instantiateViewController(withIdentifier: "settingvc")
            self.navigationController?.pushViewController(settingsViewController, animated: true)
        case 5:
            let profileStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let profileViewController = profileStoryboard.instantiateViewController(withIdentifier: "profilevc")
            self.navigationController?.pushViewController(profileViewController, animated: true)
        default:
            break
        }
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        inputTextField.resignFirstResponder()
        inputTextField.endEditing(true)
    }

}

extension ChatLogController: UITextFieldDelegate {

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        inputTextField.endEditing(true)
        return true
    }
}

设计 请参见[此链接] [1]的屏幕部分。

已实现设计:

[![screenshot1][2]][2]
[![screenshot2][3]][3]
[![screenshot3][4]][4]
[![screenshot4][5]][5]

  [1]: https://blubyn.com/
  [2]: https://i.stack.imgur.com/S9ZLX.png
  [3]: https://i.stack.imgur.com/wLvAu.png
  [4]: https://i.stack.imgur.com/nBKbH.png
  [5]: https://i.stack.imgur.com/Sota4.png

0 个答案:

没有答案