【发布时间】:2021-12-31 09:37:50
【问题描述】:
我面临的问题本身很容易描述。
我的应用程序中有一个表格视图,其中动画是异步启动的。对于一次索引路径,动画只发生一次。如果我将单元格滚动到可见区域之外,我假设该索引路径的动画已完成。即下次索引路径回到可见区域时,我将其设置为最终值,没有动画。如果我不滚动,动画会按预期工作。
但是,当我滚动表格视图时,因为单元格被重复使用,并且打算在当前不可见的单元格上执行的动画仍在现在可见的单元格上执行。 我整理了一个描述我的问题的示例代码。
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath)
cell.textLabel?.layer.opacity = 1
UIView.animate(withDuration: 2, delay: 0, options: .curveEaseIn) { [weak cell] in
cell?.textLabel?.layer.opacity = 0
} completion: { [weak cell] _ in
cell?.textLabel?.layer.opacity = 0
cell?.textLabel?.text = "\(indexPath.row)"
UIView.animate(withDuration: 2, delay: 0, options: .curveEaseIn) { [weak cell] in
cell?.textLabel?.layer.opacity = 1
} completion: { [weak cell] _ in
cell?.textLabel?.layer.opacity = 1
cell?.textLabel?.text = "\(indexPath.row)"
}
}
animated[indexPath.row].toggle()
return cell
}
}
为了在单元格超出表格视图范围时停止动画,我尝试将动画的引用保存在单元格中,并在单元格出列后立即删除。但这对我的情况没有帮助。
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
}
var animated: [Bool] = Array(repeating: false, count: 100)
}
class TestCell: UITableViewCell {
var animations: [UIViewPropertyAnimator] = []
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as! TestCell
if !animated[indexPath.row] {
//Stop animations if any
cell.animations.forEach { animator in
animator.stopAnimation(true)
}
cell.animations.removeAll()
//
let animator = UIViewPropertyAnimator(duration: 5, curve: .easeIn) { [weak cell] in
cell?.textLabel?.layer.opacity = 0
}
animator.addCompletion { [weak cell] completed in
cell?.textLabel?.layer.opacity = 0
cell?.textLabel?.text = "\(indexPath.row)"
if completed == .end {
let animator1 = UIViewPropertyAnimator(duration: 5, curve: .easeIn) { [weak cell] in
cell?.textLabel?.layer.opacity = 1
}
animator1.addCompletion { [weak cell] _ in
cell?.textLabel?.layer.opacity = 1
cell?.textLabel?.text = "\(indexPath.row)"
}
animator1.startAnimation(afterDelay: 0)
cell?.animations.append(animator1)
}
}
animator.startAnimation(afterDelay: 0)
cell.animations.append(animator)
animated[indexPath.row].toggle()
} else {
cell.textLabel?.layer.opacity = 1
cell.textLabel?.text = "\(indexPath.row)"
}
return cell
}
}
我在 SO 上找不到类似的东西。任何帮助表示赞赏。
【问题讨论】:
-
在单元格类中添加动画师并在单元格中使用 prepareForReuse 来停止它
-
您是否尝试在单元格滚动出视图时“暂停”动画,然后在单元格滚动回视图时“恢复”动画?
-
@DonMag 不,如果单元格滚动到可见区域之外,我假设该索引路径的动画已完成。对于单个索引路径,动画只需要发生一次。
标签: ios swift uitableview uikit