当我在 CollectionView 中向下滚动时,图片消失了

Posted

技术标签:

【中文标题】当我在 CollectionView 中向下滚动时,图片消失了【英文标题】:Pictures disappear when I scroll down in CollectionView 【发布时间】:2019-03-02 10:35:37 【问题描述】:

我有一个用于显示帖子的 collectionView,我有 3 种不同的帖子类型(文本、图像和视频)。我已经向单元格添加了一个图像视图,并且我在 cellForItemAt 函数中使用 if else 代码来显示图像和视频帖子的图像视图,或者使用 heightAnchor = 0 隐藏它来显示文本帖子。

它在开始时加载正确,但是当我向下滚动并再次向上滚动时,每个帖子的图像 heightAnchor 重置为“0”。我该如何解决这个问题?

帖子加载时

当我向下滚动并再次向上滚动时

TimelinePosts CollectionViewCell

class TimelinePosts: UICollectionViewCell 

    let avatar: UIImageView = 
        let avatar = UIImageView()
        avatar.contentMode = .scaleAspectFill
        avatar.clipsToBounds = true
        avatar.layer.cornerRadius = 24
        avatar.translatesAutoresizingMaskIntoConstraints = false
        return avatar
    ()

    let name: UILabel = 
        let name = UILabel()
        name.numberOfLines = 1
        name.translatesAutoresizingMaskIntoConstraints = false
        return name
    ()

    let content: ActiveLabel = 
        let content = ActiveLabel()
        content.numberOfLines = 0
        content.font = UIFont.systemFont(ofSize: 15)
        content.translatesAutoresizingMaskIntoConstraints = false
        return content
    ()

    let image: UIImageView = 
        let image = UIImageView()
        image.contentMode = .scaleAspectFill
        image.clipsToBounds = true
        image.layer.cornerRadius = 12
        image.translatesAutoresizingMaskIntoConstraints = false
        return image
    ()

    let time: UILabel = 
        let time = UILabel()
        time.numberOfLines = 1
        time.textColor = .gray
        time.font = UIFont.systemFont(ofSize: 14)
        time.textAlignment = .center
        time.translatesAutoresizingMaskIntoConstraints = false
        return time
    ()

    let moreButton: UIButton = 
        let button = UIButton()
        let image = UIImage(named: "arrow")
        button.setImage(image, for: .normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    ()


    let favoriteButton: FaveButton = 
        let button = FaveButton(frame: CGRect(x:0, y:0, width: 28, height: 28), faveIconNormal: UIImage(named: "favorite"))
        button.normalColor = UIColor(hexString: "#CBCBCB")
        button.selectedColor = UIColor(hexString: "#FFBE00")
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    ()

    let boostButton: FaveButton = 
        let button = FaveButton(frame: CGRect(x:0, y:0, width: 28, height: 28), faveIconNormal: UIImage(named: "boost-pressed"))
        button.normalColor = UIColor(hexString: "#CBCBCB")
        button.selectedColor = UIColor(hexString: "#6e00ff")
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    ()

    let actions: UILabel = 
        let view = UILabel()
        view.numberOfLines = 1
        view.textAlignment = .left
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    ()

    override init(frame: CGRect) 
        super.init(frame: frame)
        addViews()
        setupViews()
    

    func addViews()
        addSubview(avatar)
        addSubview(moreButton)
        addSubview(time)
        addSubview(name)
        addSubview(content)
        addSubview(image)
        addSubview(favoriteButton)
        addSubview(boostButton)
        addSubview(actions)

    

    func setupViews()

        avatar.leftAnchor.constraint(equalTo: leftAnchor, constant: 15).isActive = true
        avatar.topAnchor.constraint(equalTo: topAnchor, constant: 15).isActive = true
        avatar.widthAnchor.constraint(equalToConstant: 48).isActive = true
        avatar.heightAnchor.constraint(equalToConstant: 48).isActive = true

        moreButton.rightAnchor.constraint(equalTo: rightAnchor, constant: -18).isActive = true
        moreButton.topAnchor.constraint(equalTo: topAnchor, constant: 15).isActive = true
        moreButton.widthAnchor.constraint(equalToConstant: 14).isActive = true
        moreButton.heightAnchor.constraint(equalToConstant: 14).isActive = true

        time.leftAnchor.constraint(equalTo: leftAnchor, constant: 15).isActive = true
        time.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -10).isActive = true
        time.widthAnchor.constraint(equalToConstant: 48).isActive = true
        time.heightAnchor.constraint(equalToConstant: 20).isActive = true

        name.leftAnchor.constraint(equalTo: avatar.rightAnchor, constant: 10).isActive = true
        name.rightAnchor.constraint(equalTo: moreButton.leftAnchor, constant: -14).isActive = true
        name.topAnchor.constraint(equalTo: topAnchor, constant: 15).isActive = true
        name.heightAnchor.constraint(equalToConstant: 20).isActive = true

        content.leftAnchor.constraint(equalTo: leftAnchor, constant: 73).isActive = true
        content.rightAnchor.constraint(equalTo: rightAnchor, constant: -46).isActive = true
        content.topAnchor.constraint(equalTo: name.bottomAnchor, constant: 5).isActive = true

        image.leftAnchor.constraint(equalTo: leftAnchor, constant: 73).isActive = true
        image.rightAnchor.constraint(equalTo: rightAnchor, constant: -46).isActive = true
        image.topAnchor.constraint(equalTo: content.bottomAnchor, constant: 5).isActive = true
        image.heightAnchor.constraint(equalToConstant: ((UIScreen.main.bounds.width - 120) * 2) / 3).isActive = true

        actions.leftAnchor.constraint(equalTo: avatar.rightAnchor, constant: 10).isActive = true
        actions.rightAnchor.constraint(equalTo: moreButton.leftAnchor, constant: -14).isActive = true
        actions.topAnchor.constraint(equalTo: image.bottomAnchor, constant: 10).isActive = true
        actions.heightAnchor.constraint(equalToConstant: 20).isActive = true
        actions.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -10).isActive = true

        favoriteButton.rightAnchor.constraint(equalTo: rightAnchor, constant: -14).isActive = true
        favoriteButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -10).isActive = true
        favoriteButton.widthAnchor.constraint(equalToConstant: 20).isActive = true
        favoriteButton.heightAnchor.constraint(equalToConstant: 20).isActive = true

        boostButton.rightAnchor.constraint(equalTo: rightAnchor, constant: -14).isActive = true
        boostButton.bottomAnchor.constraint(equalTo: favoriteButton.topAnchor, constant: -12).isActive = true
        boostButton.widthAnchor.constraint(equalToConstant: 20).isActive = true
        boostButton.heightAnchor.constraint(equalToConstant: 20).isActive = true


       /* name.backgroundColor = .yellow
        content.backgroundColor = .red
        image.backgroundColor = .green */

    


    required init?(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    


还有cellForItemAt函数

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

            if indexPath.row < id.count

            cell.avatar.sd_setImage(with: URL(string: avatars[indexPath.row]))

            cell.time.text = hours[indexPath.row]

            cell.favoriteButton.isSelected = isLike[indexPath.row]
            cell.favoriteButton.isUserInteractionEnabled = true
            cell.favoriteButton.tag = indexPath.row

            cell.boostButton.isSelected = isBoost[indexPath.row]
            cell.boostButton.isUserInteractionEnabled = true
            cell.boostButton.tag = indexPath.row

            let selectedArrowTap = UITapGestureRecognizer(target: self, action: #selector(self.selectedArrow))
            selectedArrowTap.numberOfTapsRequired = 1
            cell.moreButton.isUserInteractionEnabled = true
            cell.moreButton.tag = indexPath.row
            cell.moreButton.addGestureRecognizer(selectedArrowTap)


            cell.content.customize  label in
                label.text = content[indexPath.row]
                label.hashtagColor = UIColor(hexString: "#6e00ff")
                label.mentionColor = UIColor(hexString: "#6e00ff")
                label.URLColor = UIColor(hexString: "#0366d6")
            

            cell.content.handleHashtagTap  hashtag in
                print("Success. You just tapped the \(hashtag) hashtag")
            

            cell.content.handleURLTap  url in

                let urlString = url.absoluteString

                if urlString.hasPrefix("http://")
                
                    let openURL = URL(string: urlString)!
                    let svc = SFSafariViewController(url: openURL)
                    self.present(svc, animated: true, completion: nil)
                
                else if urlString.hasPrefix("https://")
                
                    let openURL = URL(string: urlString)!
                    let svc = SFSafariViewController(url: openURL)
                    self.present(svc, animated: true, completion: nil)
                
                else
                
                    let openURL = URL(string: "https://" + urlString)!
                    let svc = SFSafariViewController(url: openURL)
                    self.present(svc, animated: true, completion: nil)
                

            



            if types[indexPath.row] == 2
                cell.image.sd_setImage(with: URL(string: images[indexPath.row]))
                let selectedImageTap = UITapGestureRecognizer(target: self, action: #selector(self.photoZoom))
                selectedImageTap.numberOfTapsRequired = 1
                cell.image.isUserInteractionEnabled = true
                cell.image.tag = indexPath.row
                cell.image.addGestureRecognizer(selectedImageTap)

            else if types[indexPath.row] == 3
                cell.image.sd_setImage(with: URL(string: "https://i.ytimg.com/vi/\(self.extractYoutubeIdFromLink(link: videos[indexPath.row])!)/mqdefault.jpg"))

                let playBtn = UIImageView()
                playBtn.image = UIImage(named: "youtube-play")
                playBtn.tag = indexPath.row
                playBtn.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.videoPlay)))
                playBtn.isUserInteractionEnabled = true
                playBtn.translatesAutoresizingMaskIntoConstraints = false
                cell.image.isUserInteractionEnabled = true

                cell.image.addSubview(playBtn)

                playBtn.centerXAnchor.constraint(equalTo: cell.image.centerXAnchor).isActive = true
                playBtn.centerYAnchor.constraint(equalTo: cell.image.centerYAnchor).isActive = true
                playBtn.widthAnchor.constraint(equalToConstant: 74).isActive = true
                playBtn.heightAnchor.constraint(equalToConstant: 52).isActive = true



            else
                cell.image.heightAnchor.constraint(equalToConstant: 0).isActive = true
            


            return cell
        

【问题讨论】:

我建议你制作两个不同的单元格。一种用于带图像的文本,另一种用于仅文本。然后根据数据源中的数据进行双端队列。它会让你的生活更轻松,你的 cellForItem 也会变得更干净。 @GaloTorresSevilla 谢谢,我按照你说的做了,但我想也许会有最简单的方法来做到这一点。再次感谢:) 这实际上是最简单的方法。这似乎是不必要的额外编码,但实际上是值得的 :)。祝你好运! @GaloTorresSevilla,谢谢你的信息:) 【参考方案1】:

你不应该修改图片高度

cell.image.heightAnchor.constraint(equalToConstant: 0).isActive = true

在你TimelinesPosts中创建一个新变量imageHeightConstraint

setupViews()中设置这个变量

imageHeightConstraint = image.heightAnchor.constraint(equalToConstant: ((UIScreen.main.bounds.width - 120) * 2) / 3).isActive = true

然后通过这个改变高度

// don't miss this code.
imageHeightConstraint.constant = ((UIScreen.main.bounds.width - 120) * 2) / 3
if types[indexPath.row] == 2 
//***************     
 else if types[indexPath.row] == 3 

//***************     

 else 
    imageHeightConstraint.constant = 0  

【讨论】:

感谢您的回答,@GaloTorresSevilla 说“您必须为每种类型创建不同的单元格,该方法是最干净和最简单的方法。”所以,我创建了新的单元格,它现在运行良好。再次感谢:)【参考方案2】:

UIScrollView 是父 UICollectionView。您使用 UIScrollView 和 UIScrollViewDelegate 来设置带有 va scrollOffset 的图像:CGFloat follow .y (referent code)

extension ViewController: UIScrollViewDelegate 
  func scrollViewDidScroll(_ scrollView: UIScrollView) 
    var scrollOffset : CGFloat = scrollView.contentOffset.y
    // process with scrollOffset
  

【讨论】:

感谢您的回答,@GaloTorresSevilla 说“您必须为每种类型创建不同的单元格,该方法是最干净和最简单的方法。”所以,我创建了新的单元格,它现在运行良好。再次感谢:)

以上是关于当我在 CollectionView 中向下滚动时,图片消失了的主要内容,如果未能解决你的问题,请参考以下文章

滚动时collectionview更改单元格背景图像

带有插图的 UICollectionView 不会一直向下滚动

在快速滚动collectionview时,第一行数据在最后一行重复

向上向下滚动时,collectionViewCell 图像发生变化

向下滚动时 UICollectionView 的 indexPath 发生变化

CollectionView 标题在滚动时停止刷新/重新加载数据