我有点卡住了 progressView 的动画(使用这个子类:Linear Progress View)。
只是一些背景知识,所以下面发布的代码很有意义。我创建了一个具有一些基本功能的 UICollectionViewCell
的子类。这样做的主要原因是减少样板代码。在我的 Collection View 中,我将单元格设置为我的子类并将模型对象传递给它。所有数据都正确显示,但进度 View 没有动画。我在 Collection View 上尝试过 viewWillDisplay
之类的东西,但无济于事。
如有任何建议,我们将不胜感激。 (下面的代码)
CollectionViewCell 类:
import UIKit
import ChameleonFramework
import Material
class MacrocycleCell: Cell {
var macrocycle:Macrocycle? = nil {
didSet{
if let macro = macrocycle, let start = macrocycle?.start, let completion = macrocycle?.completion {
title.text = macro.title
let percentage = Date().calculatePercentageComplete(startDate: start, completionDate: completion)
progress.setProgress(percentage, animated: true)
let difference = Date.calculateDifferenceInMonthsAndDaysBetween(start: start, end: completion)
if let monthDiff = difference.month, let dayDiff = difference.day {
if monthDiff > 0 {
detail.text = monthDiff > 1 ? "\(monthDiff) months left" : "\(monthDiff) month left"
}else{
detail.text = dayDiff > 1 ? "\(dayDiff) days left" : "\(dayDiff) day left"
}
}
}
}
}
let dropView:View = {
let view = View()
view.backgroundColor = .white
view.translatesAutoresizingMaskIntoConstraints = false
view.depthPreset = DepthPreset.depth2
return view
}()
let title:UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 18)
label.textColor = UIColor.flatBlack()
return label
}()
let progress:LinearProgressView = {
let progress = LinearProgressView()
progress.isCornersRounded = true
progress.barColor = UIColor.flatWhiteColorDark()
progress.trackColor = UIColor.flatGreen()
progress.barInset = 0
progress.minimumValue = 0
progress.maximumValue = 1
progress.animationDuration = 1
progress.translatesAutoresizingMaskIntoConstraints = false
return progress
}()
let detail:UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.light)
label.textColor = UIColor.flatGray()
return label
}()
override func drawView() {
addSubview(dropView)
dropView.addSubview(title)
dropView.addSubview(progress)
dropView.addSubview(detail)
dropView.topAnchor.constraint(equalTo: topAnchor).isActive = true
dropView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
dropView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
dropView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -2).isActive = true
progress.centerXAnchor.constraint(equalTo: dropView.centerXAnchor).isActive = true
progress.centerYAnchor.constraint(equalTo: dropView.centerYAnchor).isActive = true
progress.heightAnchor.constraint(equalToConstant: 10).isActive = true
progress.widthAnchor.constraint(equalTo: dropView.widthAnchor, multiplier: 0.8).isActive = true
title.topAnchor.constraint(equalTo: dropView.topAnchor).isActive = true
title.leftAnchor.constraint(equalTo: dropView.safeAreaLayoutGuide.leftAnchor).isActive = true
title.rightAnchor.constraint(equalTo: dropView.safeAreaLayoutGuide.rightAnchor).isActive = true
title.bottomAnchor.constraint(equalTo: progress.topAnchor, constant: 6).isActive = true
detail.topAnchor.constraint(equalTo: progress.bottomAnchor, constant: 14).isActive = true
detail.leftAnchor.constraint(equalTo: dropView.leftAnchor).isActive = true
detail.rightAnchor.constraint(equalTo: dropView.rightAnchor).isActive = true
detail.heightAnchor.constraint(equalToConstant: 14).isActive = true
}
}
CollectionViewController 类:
import UIKit
private let reuseIdentifier = "Cell"
class MacrocycleController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var athlete:Athlete? = nil {
didSet{
self.title = athlete?.name
}
}
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = .flatWhiteColorDark()
self.collectionView!.register(MacrocycleCell.self, forCellWithReuseIdentifier: reuseIdentifier)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 90)
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return athlete?.macrocycles?.count ?? 0
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! MacrocycleCell
cell.macrocycle = athlete?.macrocycles?[indexPath.item]
return cell
}
}
我确信这很简单,但我忘了实现。
谢谢你们这些美丽的人!
最佳答案
您看不到任何动画,因为没有要设置动画的可见变化。具体来说,您在显示单元格之前从 didSet 调用 setProgress,然后您再也不会调用它。
要查看动画,您必须允许 View 以某个初始值 (0%) 显示,然后再次调用 setProgress,将更改动画化为真值。
从 UI 的角度来看,您尝试做的事情不是一个好主意——原则上,进度条应该仅在发生某些实际有意义的进展(用户操作、下载等)时才移动。因此,我对你的问题的回答是在这种情况下使用没有动画的进度条。
话虽这么说,但在某些合理的情况下,您可能希望更新单元格中的进度条而不必重新加载单元格。 例如,如果您有一些正在运行的后台任务定期报告与每个单元格相关的进度。有大量的答案展示了进行这种更新的不同方法。
此外,还有一些建议用于在显示单元格后立即触发更新。如果您想查看其中一些想法,请搜索不存在的“DidDisplayCell”委托(delegate)方法的问题。您绝对可以在单元格显示之后制作动画,但我想让您远离将动画用于人为目的的诱惑。
下面是一些代码片段,用于说明如何使用 WillDisplay 中的 asyncAfter 执行此操作(我使用 tableview 对此进行了测试):
// This would be in your cell class
var progress: Float = 0.0
@IBOutlet var progressBar: LinearProgressView!
func animateIfNeeded() {
if progressBar.progress != self.progress {
progressBar.setProgress(progress, animated: true)
}
}
// This would be in your delegate (I tested with tableview)
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
let animateCell = cell as! Cell
animateCell.animateIfNeeded()
}
}
显然,在 didSet 中,您只需将计算出的值保存到一个实例变量中(progress: Float)并调用 progressBar.setProgress(0,animated: false)。
关于ios - 在 collectionviewcell 中动画化 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47242942/