在 Swift 中高亮时使 CollectionViewCell 反弹

Posted

技术标签:

【中文标题】在 Swift 中高亮时使 CollectionViewCell 反弹【英文标题】:Make a CollectionViewCell bounce on highlight in Swift 【发布时间】:2016-02-06 01:31:29 【问题描述】:

在过去的几个小时里,我尝试完成以下工作:

在 UICollectionview 中,当我突出显示(向下触摸)一个单元格时,我希望它向内反弹几个像素(到更小的尺寸)并在释放时反弹回原始尺寸。

这是我迄今为止尝试过的:

override func collectionView(collectionView: UICollectionView,
didHighlightItemAtIndexPath indexPath: NSIndexPath) 


    collectionView.collectionViewLayout.invalidateLayout()
    let cell = collectionView.cellForItemAtIndexPath(indexPath)
    UIView.transitionWithView(cell!, duration: 1, options: UIViewAnimationOptions.CurveEaseIn, animations: 

        let center = cell?.center
        let frame2 = CGRect(x: 0, y: 0, width: 50, height: 50)
        cell?.frame = frame2
        cell?.center = center!

        , completion: nil)

(我从这个问题中找到了很多这个代码示例: UICollectionView: Animate cell size change on selection 但这适用于单元格选择。不突出。 )

所以在 didHighlightItemAtIndexPath 中,我将突出显示的单元格设置为新大小。大小设置正确,但出现以下问题: 1:它没有动画, 2:它移动到位置 (0,0) 并动画回到中心位置。它根本不应该移动位置 - 只是大小。

我在 Shazam 应用中看到了这种效果,以供参考。当您在歌曲名称下方的按钮上对歌曲进行 shazam (或查看以前的 shazad 歌曲)时,可以看到它。

【问题讨论】:

【参考方案1】:

UICollectionViewCell 子类中,您可以使用以下代码。我建议不要使用touchesBegantouchesEnded,因为覆盖它们会禁用UICollectionViewdidSelectItemAt 委托方法,因此您必须通过自己的委托单独处理。如果您在视图控制器中使用didSelectItemAt 委托方法,那么正确的动画方法是覆盖isHighlighted 属性。

斯威夫特 3/4-

override var isHighlighted: Bool
        didSet
            if isHighlighted
                UIView.animate(withDuration: 0.2, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 1.0, options: .curveEaseOut, animations: 
                    self.transform = self.transform.scaledBy(x: 0.75, y: 0.75)
                , completion: nil)
            else
                UIView.animate(withDuration: 0.2, delay: 0.0, usingSpringWithDamping: 0.4, initialSpringVelocity: 1.0, options: .curveEaseOut, animations: 
                    self.transform = CGAffineTransform.identity.scaledBy(x: 1.0, y: 1.0)
                , completion: nil)
            
        
    

【讨论】:

执行此操作后,我无法在点击边缘附近时选择单元格。有什么建议吗?【参考方案2】:

Swift 4一点点重构代码

    override var isHighlighted: Bool 
        didSet  bounce(isHighlighted) 
    

    func bounce(_ bounce: Bool) 
        UIView.animate(
            withDuration: 0.8,
            delay: 0,
            usingSpringWithDamping: 0.4,
            initialSpringVelocity: 0.8,
            options: [.allowUserInteraction, .beginFromCurrentState],
            animations:  self.transform = bounce ? CGAffineTransform(scaleX: 0.9, y: 0.9) : .identity ,
            completion: nil)

    

【讨论】:

【参考方案3】:

这是一般要点,虽然它不能处理所有边缘情况。

class MyCollectionViewCell: UICollectionViewCell

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
    
        UIView.animateWithDuration(0.5)  () -> Void in
            let shrinkTransform = CGAffineTransformScale(CGAffineTransformIdentity, 0.5, 0.5)
            self.transform = shrinkTransform
        
    
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?)
    
        super.touchesEnded(touches, withEvent: event)
        UIView.animateWithDuration(0.5)  () -> Void in
            self.transform = CGAffineTransformIdentity
        
    


class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource 

    let l = UICollectionViewFlowLayout()
    var c: UICollectionView! = nil
    override func viewDidLoad() 
        super.viewDidLoad()
        l.itemSize = CGSize(width: 400, height: 44)
        c = UICollectionView(frame: CGRectZero, collectionViewLayout: l)
        c.delegate = self
        c.dataSource = self
        c.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: "cellID")
        view.addSubview(c)
    

    override func viewDidLayoutSubviews() 
        super.viewDidLayoutSubviews()
        c.frame = view.bounds
    
    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
    
        return 1
    
    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    
        return 100
    
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
    
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cellID", forIndexPath: indexPath) as! MyCollectionViewCell
        if cell.contentView.subviews.count == 0
        
            let label = UILabel(frame: CGRectZero)
            label.text = "Row: \(indexPath.row)"
            cell.contentView.addSubview(label)
            label.frame = cell.contentView.bounds
            cell.contentView.backgroundColor = UIColor.whiteColor()
        
        return cell
    

这是一个视频:http://cl.ly/1Z3n2S2j0K3t

对不起,糟糕的格式,妈妈打来电话,晚餐准备好了。

【讨论】:

多么棒的答案!刚刚看了视频,这正是我所追求的!如果我能让它工作,我会尝试实施它并接受答案:) 谢谢你的回答 - 希望晚餐很好!

以上是关于在 Swift 中高亮时使 CollectionViewCell 反弹的主要内容,如果未能解决你的问题,请参考以下文章

Swift UI VStack 对齐。按下时使文本字段与键盘一起出现

Xcode 7.2 语法高亮在 Swift 文件中闪烁

如何将 UIButton 的高亮属性设置为 NO?

如何在 Swift 上使这段代码异步

通过 UIButton 选择一个单元格 - CollectionViewCell - Swift

使用动态tableView的tableViewCell中的动态collectionViewCell执行Segue With Identifier,swift