ios - 无法让自定义活动指示器设置动画
问题描述
我将最初在Objc 文件中的自定义活动指示器重写为 Swift。活动指示器出现在场景中,但动画没有出现。
我需要一些帮助来弄清楚为什么动画没有发生:
vc:
class ViewController: UIViewController {
fileprivate lazy var customActivityView: CustomActivityView = {
let customActivityView = CustomActivityView()
customActivityView.translatesAutoresizingMaskIntoConstraints = false
customActivityView.delegate = self
customActivityView.numberOfCircles = 3
customActivityView.radius = 20
customActivityView.internalSpacing = 3
customActivityView.startAnimating()
return customActivityView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setAnchors()
}
fileprivate func setAnchors() {
view.addSubview(customActivityView)
customActivityView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
customActivityView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
customActivityView.widthAnchor.constraint(equalToConstant: 100).isActive = true
customActivityView.heightAnchor.constraint(equalToConstant: 100).isActive = true
}
}
extension ViewController: CustomActivityViewDelegate {
func activityIndicatorView(activityIndicatorView: CustomActivityView, circleBackgroundColorAtIndex index: Int) -> UIColor {
let red = CGFloat(Double((arc4random() % 256)) / 255.0)
let green = CGFloat(Double((arc4random() % 256)) / 255.0)
let blue = CGFloat(Double((arc4random() % 256)) / 255.0)
let alpha: CGFloat = 1
return UIColor(red: red, green: green, blue: blue, alpha: alpha)
}
}
斯威夫特文件:
import UIKit
protocol CustomActivityViewDelegate: class {
func activityIndicatorView(activityIndicatorView: CustomActivityView, circleBackgroundColorAtIndex index: Int) -> UIColor
}
class CustomActivityView: UIView {
var numberOfCircles: Int = 0
var internalSpacing: CGFloat = 0
var radius: CGFloat = 0
var delay: CGFloat = 0
var duration: CFTimeInterval = 0
var defaultColor = UIColor.systemPink
var isAnimating = false
weak var delegate: CustomActivityViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
setupDefaults()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupDefaults()
fatalError("init(coder:) has not been implemented")
}
func setupDefaults() {
self.translatesAutoresizingMaskIntoConstraints = false
numberOfCircles = 5
internalSpacing = 5
radius = 10
delay = 0.2
duration = 0.8
}
func createCircleWithRadius(radius: CGFloat, color: UIColor, positionX: CGFloat) -> UIView {
let circle = UIView(frame: CGRect(x: positionX, y: 0, width: radius * 2, height: radius * 2))
circle.backgroundColor = color
circle.layer.cornerRadius = radius
circle.translatesAutoresizingMaskIntoConstraints = false;
return circle
}
func createAnimationWithDuration(duration: CFTimeInterval, delay: CGFloat) -> CABasicAnimation {
let anim: CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation")
anim.fromValue = 0.0
anim.toValue = 1.0
anim.autoreverses = true
anim.duration = duration
anim.isRemovedOnCompletion = false
anim.beginTime = CACurrentMediaTime()+Double(delay)
anim.repeatCount = .infinity
anim.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
return anim;
}
func addCircles() {
for i in 0..<numberOfCircles {
var color: UIColor?
color = delegate?.activityIndicatorView(activityIndicatorView: self, circleBackgroundColorAtIndex: i)
let circle = createCircleWithRadius(radius: radius,
color: ((color == nil) ? self.defaultColor : color)!,
positionX: CGFloat(i) * ((2 * self.radius) + self.internalSpacing))
circle.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
circle.layer.add(self.createAnimationWithDuration(duration: self.duration,
delay: CGFloat(i) * self.delay), forKey: "scale")
self.addSubview(circle)
}
}
func removeCircles() {
self.subviews.forEach({ $0.removeFromSuperview() })
}
@objc func startAnimating() {
if !isAnimating {
addCircles()
self.isHidden = false
isAnimating = true
}
}
@objc func stopAnimating() {
if isAnimating {
removeCircles()
self.isHidden = true
isAnimating = false
}
}
func intrinsicContentSize() -> CGSize {
let width: CGFloat = (CGFloat(self.numberOfCircles) * ((2 * self.radius) + self.internalSpacing)) - self.internalSpacing
let height: CGFloat = radius * 2
return CGSize(width: width, height: height)
}
func setNumberOfCircles(numberOfCircles: Int) {
self.numberOfCircles = numberOfCircles
self.invalidateIntrinsicContentSize()
}
func setRadius(radius: CGFloat) {
self.radius = radius
self.invalidateIntrinsicContentSize()
}
func setInternalSpacing(internalSpacing: CGFloat) {
self.internalSpacing = internalSpacing
self.invalidateIntrinsicContentSize()
}
}
解决方案
我为动画使用了错误的键路径:
我用了
// incorrect
let anim: CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation")
但我应该使用
// correct
let anim: CABasicAnimation = CABasicAnimation(keyPath: "transform.scale")
推荐阅读
- laravel - Laravel - POSTMAN 上的 500 内部服务器错误
- python - Python - 将频道添加到类别
- javascript - 扩展类的属性,扩展类的 Getter。永远不会调用 Getter
- xaml - ListView 中的项目如何从右到左开始?
- linux - 仅当所有模式在同一订单上匹配时才提取多行
- unity3d - 构建后我没有为我的游戏获取 .exe?
- react-native - TouchableWithoutFeedback 抛出渲染错误
- android - 从图像中删除特定颜色
- rest - 通过 jmeter 模拟并行端点 api 使用
- scala - 有没有办法从 Spark Context 访问 RDD 分区信息?