重新加载数据后,如何使 UICollectionView 从底部滚动到聊天应用程序?

How to make UICollectionView scroll from bottom for chat application after reload data?

我想在用户单击发送消息 UIButton 时从下到上滚动我的 UICollectionView,并且当用户再次打开应用程序时,最后发送的消息必须首先在底部看到。

我刚刚尝试了所有堆栈溢出答案和其他站点代码,但找不到任何解决我的问题的方法。

import UIKit
import Kingfisher
import Firebase
import IQKeyboardManagerSwift

class FireStoreChatViewController: UIViewController, UITextViewDelegate,UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
{
    @IBOutlet var collectionView: UICollectionView!
    @IBOutlet weak var sendMessageBtn: UIButton!

    var comeFrom : String = ""
    var mChatUser : String = ""
    var mChatUserName : String = ""
    var mCurruntUserId : String = ""
    var isFirstPageFirstLoad: Bool = false
    var lastVisible: DocumentSnapshot? = nil
    var messageList: [Messages] = []

    override func viewDidLoad()
    {
        super.viewDidLoad()
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        self.messageList.reverse()
        return messageList.count
    }


    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    {
       if messageList[indexPath.row].from == mCurruntUserId
       {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Message", for: indexPath as IndexPath) as! MessageCollectionViewCell

       }

      return cell
    }

    @IBAction func sendMessageAction(_ sender: UIButton)
    {
        sendMessage()
    }

    func getMessage(mChatUser: String, mCurruntUser: String)
    { 
       // code
    }

    func sendMessage()
    {
       // code
    }

    func updateChatListData()
    {
       // code
    }


}

输出

First index path seen first while open chat app module.

重新加载 collectionview 后添加以下代码:

let ipath = IndexPath(row: messageList.count - 1, section: 0)
collectionView.scrollToItem(at: ipath, at: .bottom, animated: false)

如果你想从底部开始收集视图,你必须旋转 collectionView 和它的单元格。

首先在ViewdidLoad中旋转collectionView

yourCollectionView.transform = CGAffineTransform.init(rotationAngle: (-(CGFloat)(Double.pi)))

比在 cellforitematindexpath 中旋转单元格

cell.transform = CGAffineTransform(rotationAngle: CGFloat.pi)

您可以将 Vinod Jacob 的回答中给出的 scrollToItem 语法放入其中。 DispatchQueue.main.async { let ipath = IndexPath(row: messageList.count - 1, section: 0) collectionView.scrollToItem(at: ipath, at: .bottom, animated: false) }

要让 collectionView 从底部填充,您可以在 collectionView 重新加载时修改 collectionView 的顶部插图,

调用 reloadData() 后调用:

func updateCollectionContentInset() {
    let contentSize = yourCollectionView.collectionViewLayout.collectionViewContentSize
    var contentInsetTop = yourCollectionView.bounds.size.height

        contentInsetTop -= contentSize.height
        if contentInsetTop <= 0 {
            contentInsetTop = 0
    }
    yourCollectionView.contentInset = UIEdgeInsets(top: contentInsetTop,left: 0,bottom: 0,right: 0)
}

然后在需要时滚动到底部(在重新加载 collectionView 并更新内容插图后在数据源的 didSet 中),调用:

func scrollToBottom() {

    guard !yourDataSource.isEmpty else { return }

    let lastIndex = yourDataSource.count - 1

     yourCollectionView.scrollToItem(at: IndexPath(item: lastIndex, section: 0), at: .centeredVertically, animated: true)

}

在 CollectionView 中从 api 加载聊天后使用此代码。

DispatchQueue.main.async(execute: {

            self.mycollectionView.reloadData()
            self.scrollToBottom()
            //self.table1.setContentOffset(CGPoint(x: 0, y: self.table1.contentSize.height - UIScreen.main.bounds.height), animated: true)
        })