为什么collectionView.scrollToItem使用Swift将indexPath滚动到视图之外?

时间:2018-08-09 06:42:30

标签: ios swift uicollectionview

以下函数加载Messages的数组,重新加载collectionView并(应)滚动到最后一项。

问题是最后一项在视图的上方和下方滚动太远,因此不可见。

注意:我使用的是3个不同的“原型”自动调整大小的单元,这些单元根据消息的类型(文本消息,图像消息等)而出队。

这似乎是一个简单的任务,但是我开始努力做到这一点。任何帮助都会很棒:)

func loadConversation(){


    DataService.run.observeUsersMessagesFor(forUserId: chatPartnerId!) { (chatLog) in
        self.messages = chatLog
        self.collectionView.reloadData()

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


    }

}//end func

编辑:numberOfItemsInSection函数

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

        return messages.count

    }

编辑:cellForItemAt

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

        let message = messages[indexPath.item]

        let uid = Auth.auth().currentUser?.uid

        if message.fromId == uid {

            if message.imageUrl != nil {
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ConversationCellImage", for: indexPath) as! ConversationCellImage
                cell.configureCell(message: message)
                return cell

            } else {
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ConversationCellSender", for: indexPath) as! ConversationCellSender
                cell.configureCell(message: message)
                return cell

            }//end if message.imageUrl != nil


        } else {

            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ConversationCell", for: indexPath) as! ConversationCell
            cell.configureCell(message: message)
            return cell

        }//end if 

    }//end func

编辑:ConversationCell Class,它将自动调整单元格的高度。

class ConversationCell: UICollectionViewCell {

    @IBOutlet weak var chatPartnerProfileImg: CircleImage!
    @IBOutlet weak var messageLbl: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()

        chatPartnerProfileImg.isHidden = false

    }//end func

    func configureCell(message: Message){

        messageLbl.text = message.message

        let partnerId = message.chatPartnerId()

        DataService.run.getUserInfo(forUserId: partnerId!) { (user) in
            let url = URL(string: user.profilePictureURL)
            self.chatPartnerProfileImg.sd_setImage(with: url, placeholderImage:  #imageLiteral(resourceName: "placeholder"), options: [.continueInBackground, .progressiveDownload], completed: nil)

        }//end getUserInfo

    }//end func


    override func layoutSubviews() {
        super.layoutSubviews()

        self.layer.cornerRadius = 10.0
        self.layer.shadowRadius = 5.0
        self.layer.shadowOpacity = 0.3
        self.layer.shadowOffset = CGSize(width: 5.0, height: 10.0)
        self.clipsToBounds = false

    }//end func



    override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
        //toggles auto-layout
        setNeedsLayout()
        layoutIfNeeded()

        //Tries to fit contentView to the target size in layoutAttributes
        let size = contentView.systemLayoutSizeFitting(layoutAttributes.size)

        //Update layoutAttributes with height that was just calculated
        var frame = layoutAttributes.frame
        frame.size.height = ceil(size.height) + 18
        layoutAttributes.frame = frame
        return layoutAttributes
    }



}//end class

1 个答案:

答案 0 :(得分:2)

您应该在主线程上执行与UI相关的任务。按照以下步骤更新您的函数loadConversation

func loadConversation() {
DataService.run.observeUsersMessagesFor(forUserId: chatPartnerId!) { (chatLog) in
    self.messages = chatLog
    DispatchQueue.main.async {
    self.collectionView.reloadData()
    self.collectionView.layoutIfNeeded()

    if self.messages.count > 0 {
        let indexPath = IndexPath(item: self.messages.count - 1, section: 0)
        // set animated false/true, based on the new messages. if many new messages keep it false
        self.collectionView.scrollToItem(at: indexPath, at: .bottom , animated: true)
    }
  }
 }
}

编辑

闪烁是由于设置了userImage。它应该在主线程上。 将其更新为

DispatchQueue.main.async {
     self.chatPartnerProfileImg.sd_setImage(with: url, placeholderImage:  #imageLiteral(resourceName: "placeholder"), options: [.continueInBackground, .progressiveDownload], completed: nil)
}

尝试并分享结果。