Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have collection view cells and I'd like to animate all of them at the same time. Even though I'm using UIView.animate the animation does not happen and affine transform happens instantaneously.

enter image description here

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
    var collectionview: UICollectionView!
    var moveText: Bool = false

    override func viewDidLoad() {
        super.viewDidLoad()
        
        collectionview = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
        collectionview.translatesAutoresizingMaskIntoConstraints = false
        collectionview.dataSource = self
        collectionview.delegate = self
        collectionview.backgroundColor = .systemBackground
        collectionview.register(MyCell.self, forCellWithReuseIdentifier: "cell")
        view.addSubview(collectionview)
        
        NSLayoutConstraint.activate([
            collectionview.topAnchor.constraint(equalTo: view.topAnchor),
            collectionview.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            collectionview.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            collectionview.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        ])
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        10
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionview.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCell
        cell.moveText = moveText
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return .init(width: collectionview.frame.width, height: 120)
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { timer in
            UIView.animate(withDuration: 1, delay: 0) {
                print("Starting animatings")
                self.moveText = !self.moveText
                self.collectionview.reloadData()
            }
        }
    }
    
}

class MyCell: UICollectionViewCell {
    
    let label = UILabel()
    var moveText: Bool = false {
        didSet {
            if moveText == true {
                label.transform = CGAffineTransform(translationX: 50, y: 50)
            } else {
                label.transform = CGAffineTransform(translationX: 0, y: 0)
            }
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        label.text = "mytext"
        label.translatesAutoresizingMaskIntoConstraints = false
        addSubview(label)
        NSLayoutConstraint.activate([
            label.leadingAnchor.constraint(equalTo: leadingAnchor),
            label.topAnchor.constraint(equalTo: topAnchor)
        ])
        backgroundColor = .orange
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
346 views
Welcome To Ask or Share your Answers For Others

1 Answer

This is because you are animating the wrong thing.

// adding weak self so the timer will not retain the view controller
Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { [weak self] timer in
    self?.moveText.toggle() // you can use toggle() on a `Bool`
    self?.collectionview.reloadData()
}

Instead, you should try to animate setting the value of individual cell

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionview.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCell
    UIView.animate(withDuration: 1, delay: 0) {
        cell.moveText = self.moveText
    }
    return cell
}

Also, instead of using CGAffineTransform(translationX: 0, y: 0) you could use .identity

label.transform = .identity

Worth noting is the fact that reloading collection view every 2 seconds and animating directly in cellForItemAt is very inefficient. You should find another way to pass information to the cell's they should animate the content


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...