您已经很接近了...只需进行一些更改即可到达您想要的位置。
如果您有一个UILabel 和一个UIImageView(或普通UIView)被限制在标签的右边缘,您应该能够定位您的CAReplicatorLayer,而不必担心“屏幕尺寸”。
看看我是如何修改你的代码的:
// baseline = to put the bottom of the dots at the baseline of the text in the label
// dotXOffset = gap between end of label and first dot
// dotSize = dot width and height
// dotSpacing = gap between dots
func showAnimatingDotsInImageView(dotsView: UIView, baseline: CGFloat, dotXOffset: CGFloat, dotSize: CGFloat, dotSpacing: CGFloat) {
let lay = CAReplicatorLayer()
let bar = CALayer()
bar.frame = CGRect(x: dotXOffset, y: baseline - dotSize, width: dotSize, height: dotSize)
bar.cornerRadius = bar.frame.width / 2 // we want round dots
bar.backgroundColor = UIColor.black.cgColor
lay.addSublayer(bar)
lay.instanceCount = 3 //How many instances / objs do you want to see
lay.instanceTransform = CATransform3DMakeTranslation(dotSpacing, 0, 0) //1st arg is the spacing between the instances
let anim = CABasicAnimation(keyPath: #keyPath(CALayer.opacity))
anim.fromValue = 1.0
anim.toValue = 0.2
anim.duration = 1
anim.repeatCount = .infinity
bar.add(anim, forKey: nil)
lay.instanceDelay = anim.duration / Double(lay.instanceCount)
dotsView.layer.addSublayer(lay) // add to the view
}
这是一个完整的例子:
class SimpleViewController: UIViewController {
let testLabel = UILabel()
let testDotsView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
testLabel.font = .systemFont(ofSize: 24.0)
testLabel.text = "Retrieving boxes"
// so we can see the label frame
testLabel.backgroundColor = .cyan
testLabel.translatesAutoresizingMaskIntoConstraints = false
testDotsView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(testLabel)
view.addSubview(testDotsView)
// always respect safe area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// let's constrain the label
// 40-pts from Leading
// 40-pts from Bottom
testLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
testLabel.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -40.0),
// constrain dots view to
// Top of label
// Trailing of label
testDotsView.topAnchor.constraint(equalTo: testLabel.topAnchor),
testDotsView.leadingAnchor.constraint(equalTo: testLabel.trailingAnchor, constant: 0.0),
// dots image view Width and Height can be 0 (we can draw the layer outside the bounds)
testDotsView.heightAnchor.constraint(equalToConstant: 0.0),
testDotsView.widthAnchor.constraint(equalToConstant: 0.0),
])
// get the label font's baseline y-value
let bl: CGFloat = testLabel.font.ascender
showAnimatingDotsInImageView(dotsView: testDotsView, baseline: bl, dotXOffset: 4.0, dotSize: 4.0, dotSpacing: 8.0)
}
// baseline = to put the bottom of the dots at the baseline of the text in the label
// dotXOffset = gap between end of label and first dot
// dotSize = dot width and height
// dotSpacing = gap between dots
func showAnimatingDotsInImageView(dotsView: UIView, baseline: CGFloat, dotXOffset: CGFloat, dotSize: CGFloat, dotSpacing: CGFloat) {
let lay = CAReplicatorLayer()
let bar = CALayer()
bar.frame = CGRect(x: dotXOffset, y: baseline - dotSize, width: dotSize, height: dotSize)
bar.cornerRadius = bar.frame.width / 2 // we want round dots
bar.backgroundColor = UIColor.black.cgColor
lay.addSublayer(bar)
lay.instanceCount = 3 //How many instances / objs do you want to see
lay.instanceTransform = CATransform3DMakeTranslation(dotSpacing, 0, 0) //1st arg is the spacing between the instances
let anim = CABasicAnimation(keyPath: #keyPath(CALayer.opacity))
anim.fromValue = 1.0
anim.toValue = 0.2
anim.duration = 1
anim.repeatCount = .infinity
bar.add(anim, forKey: nil)
lay.instanceDelay = anim.duration / Double(lay.instanceCount)
dotsView.layer.addSublayer(lay) // add to the view
}
}