从UICollectionView cellForItemAt indexPath为CAShapeLayer动画设置toValue

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从UICollectionView cellForItemAt indexPath为CAShapeLayer动画设置toValue相关的知识,希望对你有一定的参考价值。

我有以下几个部分: - 我的主视图是带有UICollectionView的UIViewController - UICollectionView的单元格 - 用于构建带有CABasicAnimation的CAShapeLayer的UIView的子类

在我的主视图中,我有一个UICollectionView,它渲染了一堆带有标签等的单元格。它还显示了一个进度图。

在我的子类ProgressCirclePath()中,我绘制了一个CAShapeLayer,它充当在我的UICollectionView的每个单元格中呈现的进度图。

我已经能够将数据传递到每个单元格,例如标签以及CAShapeLayer strokeEnd值。

一切都很好,直到我尝试将CABasicAnimation添加到我的路径。在这种情况下,我无法设置动画toValue的值。使用打印控制台测试显示该值在我的UICollectionView中可用,但在我的子类中的动画块中不可用(它只是返回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
}

我的单元类中的设置:

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 cellForItemAt indexPath为CAShapeLayer动画设置toValue的主要内容,如果未能解决你的问题,请参考以下文章

如何将 UICollectionViewCell 从一个 UICollectionView 拖到另一个 UICollectionView?

UICollectionView 从纵向到横向

从 UICollectionView 中删除一个项目

从 UICollectionview 隐藏部分

通过 NSNotification 从 UICollectionView 中删除单元格

无法从 UITableViewCell 加载 UICollectionView