从 UICollectionView cellForItemAt indexPath 为 CAShapeLayer 动画设置 toValue
Setting toValue for CAShapeLayer animation from UICollectionView cellForItemAt indexPath
我有以下部分:
- 我的主视图是一个带有 UICollectionView 的 UIViewController
- UICollectionView 的单元格
- UIView 的子class,用于构建带有 CABasicAnimation
的 CAShapeLayer
在我的主视图中,我有一个 UICollectionView,它呈现了一堆带有标签等的单元格。它还显示了一个进度图。
在我的 subclass ProgressCirclePath() 中,我正在绘制一个 CAShapeLayer,它充当在我的 UICollectionView 的每个单元格中呈现的进度图。
我已经能够将数据传递到每个单元格,例如标签以及 CAShapeLayer strokeEnd 值。
一切都很好,直到我尝试将 CABasicAnimation 添加到我的路径中。在这种情况下,我无法将动画的值设置为值。使用打印控制台进行的测试表明,该值在我的 UICollectionView 中可用,但在我的子类的动画块中不可用(它只是 returns nil)。我试过简单地设置 toValue 以及在我的 ProgressCirlePath 中创建一个变量并从 UICollectionView 中设置它。都没有用。
如果能提供任何关于为什么会发生这种情况以及如何解决的提示,我将不胜感激。谢谢!!
在我的 UICollectionView 中:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = decksCollectionView.dequeueReusableCell(withReuseIdentifier: "DeckCell", for: indexPath) as! DeckCell
cell.creatorLabel.text = deckCellCreator[indexPath.item]
cell.titleLabel.text = deckCellTitle[indexPath.item]
cell.progressLabel.text = "\(deckCellCompletionPercentage[indexPath.item])%"
cell.progressGraphView.animation.toValue = CGFloat(deckCellCompletionPercentage[indexPath.item])/100
return cell
}
我小区内的设置 class:
let progressGraphView: ProgressCirclePath = {
let circlePath = ProgressCirclePath(frame: CGRect(x:0, y:0, width: 86, height: 86))
circlePath.progressLayer.position = circlePath.center
circlePath.progressBackgroundLayer.position = circlePath.center
circlePath.translatesAutoresizingMaskIntoConstraints = false
return circlePath
}()
这是我的 ProgressCirclePath()
class ProgressCirclePath: UIView {
let progressLayer = CAShapeLayer()
let progressBackgroundLayer = CAShapeLayer()
let animation = CABasicAnimation(keyPath: "strokeEnd")
// var percentageValue = CGFloat()
override init(frame: CGRect) {
super.init(frame: frame)
layer.addSublayer(progressBackgroundLayer)
layer.addSublayer(progressLayer)
let circularPath = UIBezierPath(arcCenter: .zero, radius: 43, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
progressBackgroundLayer.path = circularPath.cgPath
progressBackgroundLayer.lineWidth = 10
progressBackgroundLayer.strokeStart = 0
progressBackgroundLayer.strokeEnd = 1
progressBackgroundLayer.strokeColor = UIColor(red: 221/255.0, green: 240/255.0, blue: 226/255.0, alpha: 1.0).cgColor
progressBackgroundLayer.fillColor = UIColor.clear.cgColor
progressBackgroundLayer.transform = CATransform3DMakeRotation(-CGFloat.pi/2, 0, 0, 1)
progressLayer.path = circularPath.cgPath
progressLayer.lineWidth = 10
progressLayer.lineCap = kCALineCapRound
progressLayer.strokeColor = UIColor(red: 72/255.0, green: 172/255.0, blue: 104/255.0, alpha: 1.0).cgColor
progressLayer.fillColor = UIColor.clear.cgColor
progressLayer.transform = CATransform3DMakeRotation(-CGFloat.pi/2, 0, 0, 1)
animation.duration = 1
animation.fromValue = 0
// animation.toValue = percentageValue
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
progressLayer.add(animation, forKey: "animateGraph")
print("animation.toValue \(animation.toValue)")
}
required init?(coder aDecoder: NSCoder) {
fatalError("has not been implemented")
}
}
您在自定义视图的生命周期中过早地处理数据和动画的注入。不要在对象的初始值设定项中处理它们,而是将它们移到更晚的更合适的方法中,例如 layoutSubviews
:
override open func layoutSubviews() {
super.layoutSubviews()
// handle post-init stuff here, like animations and passing in data
// when it doesn't get passed in on init
}
我有以下部分: - 我的主视图是一个带有 UICollectionView 的 UIViewController - UICollectionView 的单元格 - UIView 的子class,用于构建带有 CABasicAnimation
的 CAShapeLayer在我的主视图中,我有一个 UICollectionView,它呈现了一堆带有标签等的单元格。它还显示了一个进度图。
在我的 subclass ProgressCirclePath() 中,我正在绘制一个 CAShapeLayer,它充当在我的 UICollectionView 的每个单元格中呈现的进度图。
我已经能够将数据传递到每个单元格,例如标签以及 CAShapeLayer strokeEnd 值。
一切都很好,直到我尝试将 CABasicAnimation 添加到我的路径中。在这种情况下,我无法将动画的值设置为值。使用打印控制台进行的测试表明,该值在我的 UICollectionView 中可用,但在我的子类的动画块中不可用(它只是 returns nil)。我试过简单地设置 toValue 以及在我的 ProgressCirlePath 中创建一个变量并从 UICollectionView 中设置它。都没有用。
如果能提供任何关于为什么会发生这种情况以及如何解决的提示,我将不胜感激。谢谢!!
在我的 UICollectionView 中:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = decksCollectionView.dequeueReusableCell(withReuseIdentifier: "DeckCell", for: indexPath) as! DeckCell
cell.creatorLabel.text = deckCellCreator[indexPath.item]
cell.titleLabel.text = deckCellTitle[indexPath.item]
cell.progressLabel.text = "\(deckCellCompletionPercentage[indexPath.item])%"
cell.progressGraphView.animation.toValue = CGFloat(deckCellCompletionPercentage[indexPath.item])/100
return cell
}
我小区内的设置 class:
let progressGraphView: ProgressCirclePath = {
let circlePath = ProgressCirclePath(frame: CGRect(x:0, y:0, width: 86, height: 86))
circlePath.progressLayer.position = circlePath.center
circlePath.progressBackgroundLayer.position = circlePath.center
circlePath.translatesAutoresizingMaskIntoConstraints = false
return circlePath
}()
这是我的 ProgressCirclePath()
class ProgressCirclePath: UIView {
let progressLayer = CAShapeLayer()
let progressBackgroundLayer = CAShapeLayer()
let animation = CABasicAnimation(keyPath: "strokeEnd")
// var percentageValue = CGFloat()
override init(frame: CGRect) {
super.init(frame: frame)
layer.addSublayer(progressBackgroundLayer)
layer.addSublayer(progressLayer)
let circularPath = UIBezierPath(arcCenter: .zero, radius: 43, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
progressBackgroundLayer.path = circularPath.cgPath
progressBackgroundLayer.lineWidth = 10
progressBackgroundLayer.strokeStart = 0
progressBackgroundLayer.strokeEnd = 1
progressBackgroundLayer.strokeColor = UIColor(red: 221/255.0, green: 240/255.0, blue: 226/255.0, alpha: 1.0).cgColor
progressBackgroundLayer.fillColor = UIColor.clear.cgColor
progressBackgroundLayer.transform = CATransform3DMakeRotation(-CGFloat.pi/2, 0, 0, 1)
progressLayer.path = circularPath.cgPath
progressLayer.lineWidth = 10
progressLayer.lineCap = kCALineCapRound
progressLayer.strokeColor = UIColor(red: 72/255.0, green: 172/255.0, blue: 104/255.0, alpha: 1.0).cgColor
progressLayer.fillColor = UIColor.clear.cgColor
progressLayer.transform = CATransform3DMakeRotation(-CGFloat.pi/2, 0, 0, 1)
animation.duration = 1
animation.fromValue = 0
// animation.toValue = percentageValue
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
progressLayer.add(animation, forKey: "animateGraph")
print("animation.toValue \(animation.toValue)")
}
required init?(coder aDecoder: NSCoder) {
fatalError("has not been implemented")
}
}
您在自定义视图的生命周期中过早地处理数据和动画的注入。不要在对象的初始值设定项中处理它们,而是将它们移到更晚的更合适的方法中,例如 layoutSubviews
:
override open func layoutSubviews() {
super.layoutSubviews()
// handle post-init stuff here, like animations and passing in data
// when it doesn't get passed in on init
}