在 CollectionViewCell 中上移标签动画

Posted

技术标签:

【中文标题】在 CollectionViewCell 中上移标签动画【英文标题】:Move up label animation inside CollectionViewCell 【发布时间】:2017-08-09 11:28:49 【问题描述】:

我用未知数量的单元格水平滚动CollectionView,它占据了除导航栏以外的整个屏幕。还有CollectionViewCell,它占用了整个CollectionView。此外,在这个单元格中,我将UIView 居中,其中包含一些标签和一个按钮。这就是我的 UI 的样子:click。

每当用户单击此 UIView 内的按钮时,标签会向上移动一点,并且所有其他标签也会变得可见。如果该模式已经被激活,按钮的工作方式相反:

class WordCell: UICollectionViewCell 

    var isActive = false
@IBOutlet weak var word: UILabel!
    @IBOutlet weak var translation: UILabel!
    @IBOutlet weak var exOne: UILabel!
    @IBOutlet weak var exTwo: UILabel!

// ...

@IBAction func move(_ sender: UIButton) 
        if !isActive 
        UIView.animate(withDuration: 0.25, animations: 
            self.word.frame.origin.y -= self.bounds.height / 7
        , completion: nil)
            UIView.animate(withDuration: 0.3, animations: 
                self.translation.alpha = 1
                self.exOne.alpha = 1
                self.exTwo.alpha = 1
            )
            isActive = true
         else 
            UIView.animate(withDuration: 0.25, animations: 
                self.word.frame.origin.y += self.bounds.height / 7
            , completion: nil)
            UIView.animate(withDuration: 0.3, animations: 
                self.translation.alpha = 0
                self.exOne.alpha = 0
                self.exTwo.alpha = 0
            )
        isActive = false
        
    

然后我的 UI 看起来像:click

我的收藏查看代码:

    // CollectiomView Delegate stuff, in the code above I just retrieve data from FireBase
extension RepeatController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout 

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return words.count
        
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "wordCell", for: indexPath) as! WordCell
        if words[0].lPairs == "re" 
            cell.word.text = words[indexPath.row].translation
            cell.translation.text = words[indexPath.row].word

         else 
            cell.word.text = words[indexPath.row].word
            cell.translation.text = words[indexPath.row].translation
        
        cell.exOne.text = words[indexPath.row].exOne
        cell.exTwo.text = words[indexPath.row].exTwo
        return cell
    

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
        let bounds = collectionView.bounds
        return CGSize(width: bounds.width, height: bounds.height)
    


问题:

此系统仅在我单击按钮两次时才有效(向上移动标签,然后将其返回到相同位置并隐藏所有其他标签)。否则,在 2-3 个单元格之后,所有其他标签都变得可见,主标签位于顶部,就像我在每个单元格的按钮上键入的一样(但我没有)。问题是什么?

【问题讨论】:

只是一个疯狂的猜测:这可能是单元重用的影响。通常 TableView/CollectionView 单元格是recycled/reused,数据源应该是分开的——它们只是表示。请参阅:dequeueReusableCell Documentation 以及 prepareForReuse 方法,该方法应该重置您的 WordCell @Oleg Blanutsa 每当您更新 UI 时,您应该在 DispatchQueue.main.async 块中进行,请在您的代码中进行此更改并告知结果 【参考方案1】:

由于更改是在 UI 中,所以首先我认为您应该首先将动画代码放入 DispatchQueue.main.async 块中

然后,由于您使用的是可重用的集合视图单元格,因此您在动画代码中更改的值对于被重用的单元格保持不变,因此为了在集合视图重用它们之前为这些值提供一些初始值,我们覆盖 prepareForReuse()方法并在其中给出初始值。

使用文档here中的想法

当一个视图被出列使用时,这个方法在 相应的 dequeue 方法将视图返回给您的代码。子类 可以覆盖此方法并使用它将属性重置为其 默认值,通常使视图准备好再次使用

在代码中你可以这样做:

 @IBAction func move(_ sender: UIButton) 
            if !isActive 
                 DispatchQueue.main.async 
                          UIView.animate(withDuration: 0.25, animations: 
                          self.word.frame.origin.y -= self.bounds.height / 7
                          , completion: nil)
                               UIView.animate(withDuration: 0.3, animations: 
                               self.translation.alpha = 1
                               self.exOne.alpha = 1
                               self.exTwo.alpha = 1
                          )

                  
                          isActive = true
             else 
                 DispatchQueue.main.async 
                         UIView.animate(withDuration: 0.25, animations: 
                         self.word.frame.origin.y += self.bounds.height / 7
                         , completion: nil)
                         UIView.animate(withDuration: 0.3, animations: 
                               self.translation.alpha = 0
                               self.exOne.alpha = 0
                               self.exTwo.alpha = 0
                         )

                
                isActive = false
            
        
    

override func prepareForReuse() 

     super.prepareForReuse()

     self.word.frame.origin.y = self.wordTop.constant, //where wordTop is a top constraint for the word 
     isActive = false
     self.translation.alpha = 0
     self.exOne.alpha = 0
     self.exTwo.alpha = 0




【讨论】:

你能在你的帖子中显示collectionview的代码吗? 更新了我的问题 @OlegBlanutsa 我做了一些更改,请检查此代码并在遇到问题时提出问题 嗯,它解决了我以前的问题,但也创建了一个新问题。有时可移动标签会移位:click 和 click。 这个标签叫什么名字?

以上是关于在 CollectionViewCell 中上移标签动画的主要内容,如果未能解决你的问题,请参考以下文章

我可以在 1 UICollectionView 中使用 collectionViewCell 2 Cell 吗?

如何在 UICollectionView 中获取选中的 CollectionViewCell?

在 Swift 中高亮时使 CollectionViewCell 反弹

如何在collectionViewCell中使用动态大小的scrollView

动态调整 collectionViewCell 的常量以在自动布局中使用

在 CollectionViewCell 内的 ScrollView 内缩放 UIImage [重复]