MessageKit 中的自定义单元格

Custom cell in MessageKit

我正在尝试在 MessageKit 中为 gif 添加自定义单元格,我想要与 MediaMessageCell 相同,唯一不同的是 UIImageView 替换为 GPHMediaView,我扩展了MessageContentCell 并创建了一个 CustomClass。

CustomChatCell.swift

open class CustomChatCell: MessageContentCell {

    /// The image view display the media content.
    open var imageView: GPHMediaView = {
        let imageView = GPHMediaView()
        imageView.contentMode = .scaleAspectFill
        return imageView
    }()

    // MARK: - Methods

    /// Responsible for setting up the constraints of the cell's subviews.
    open func setupConstraints() {
        imageView.fillSuperview()
    }

    open override func setupSubviews() {
        super.setupSubviews()
        messageContainerView.addSubview(imageView)
        setupConstraints()
    }

    open override func prepareForReuse() {
        super.prepareForReuse()
        self.imageView.image = nil
    }

    open override func configure(with message: MessageType, at indexPath: IndexPath, and messagesCollectionView: MessagesCollectionView) {
        super.configure(with: message, at: indexPath, and: messagesCollectionView)

        guard let displayDelegate = messagesCollectionView.messagesDisplayDelegate else {
            fatalError("MessagesDisplayDelegate has not been set.")
        }

        switch message.kind {
        case .custom(let mediaItem):

            guard let media = mediaItem as? GPHMedia else { return }
            imageView.media = media

        default:
            break
        }

        displayDelegate.configureMediaMessageImageView(imageView, for: message, at: indexPath, in: messagesCollectionView)
    }

    /// Handle tap gesture on contentView and its subviews.
    open override func handleTapGesture(_ gesture: UIGestureRecognizer) {
        let touchLocation = gesture.location(in: imageView)

        guard imageView.frame.contains(touchLocation) else {
            super.handleTapGesture(gesture)
            return
        }
        delegate?.didTapImage(in: self)
    }

}

CustomMessagesFlowLayoutCustomMessageSizeCalculator

open class CustomMessagesFlowLayout: MessagesCollectionViewFlowLayout {

    open lazy var customMessageSizeCalculator = CustomMessageSizeCalculator(layout: self)

    open override func cellSizeCalculatorForItem(at indexPath: IndexPath) -> CellSizeCalculator {
        if isSectionReservedForTypingIndicator(indexPath.section) {
            return typingIndicatorSizeCalculator
        }
        let message = messagesDataSource.messageForItem(at: indexPath, in: messagesCollectionView)
        if case .custom = message.kind {
            return customMessageSizeCalculator
        }
        return super.cellSizeCalculatorForItem(at: indexPath)
    }

    open override func messageSizeCalculators() -> [MessageSizeCalculator] {
        var superCalculators = super.messageSizeCalculators()
        // Append any of your custom `MessageSizeCalculator` if you wish for the convenience
        // functions to work such as `setMessageIncoming...` or `setMessageOutgoing...`
        superCalculators.append(customMessageSizeCalculator)
        return superCalculators
    }
}

open class CustomMessageSizeCalculator: MessageSizeCalculator {

    public override init(layout: MessagesCollectionViewFlowLayout? = nil) {
        super.init()
        self.layout = layout
    }

    open override func sizeForItem(at indexPath: IndexPath) -> CGSize {
        guard let layout = layout else { return .zero }
        let collectionViewWidth = layout.collectionView?.bounds.width ?? 0
        let contentInset = layout.collectionView?.contentInset ?? .zero
        let inset = layout.sectionInset.left + layout.sectionInset.right + contentInset.left + contentInset.right
        return CGSize(width: ((collectionViewWidth / 2) - inset), height: ((collectionViewWidth / 2) - inset))
    }

}

giphy 的视图不存在, avatarView 也不在中间,帮助解决这个问题,需要与光电池相同。

尝试替换整个方法

open override func sizeForItem(at indexPath: IndexPath) -> CGSize {

使用以下方法


open override func messageContainerSize(for message: MessageType) -> CGSize {
      
     guard let layout = layout else { return .zero }

     let maxWidth = messageContainerMaxWidth(for: message)

     let contentInset = layout.collectionView?.contentInset ?? .zero

     let inset = layout.sectionInset.left + layout.sectionInset.right + contentInset.left + contentInset.right
        
     return CGSize(width: ((maxWidth / 2) - inset), height: ((maxWidth / 2) - inset))
}