问题描述
我有集合视图单元格,我想同时为它们设置动画。即使我使用 UIView.animate
,动画也不会发生,仿射变换会立即发生。
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")
}
}
解决方法
这是因为你制作了错误的动画。
// 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()
}
相反,您应该尝试动画设置单个单元格的值
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
}
此外,您可以使用 CGAffineTransform(translationX: 0,y: 0)
代替 .identity
label.transform = .identity
值得注意的是,每 2 秒重新加载集合视图并直接在 cellForItemAt
中进行动画是非常低效的。您应该找到另一种方法将信息传递给单元格,它们应该为内容设置动画