在 swift iOS 中为 3 个点设置动画

Posted

技术标签:

【中文标题】在 swift iOS 中为 3 个点设置动画【英文标题】:Animating 3 dots in swift iOS 【发布时间】:2021-09-03 14:23:20 【问题描述】:

我有一个标签和一个图像视图。我的目标是在标签的前面有 3 个点动画,并在最后的标签脚下,如此处所示

我已经能够使这个设计在 12promax 上移动得很好,但是我无法弄清楚如何让这个设计始终在不同的手机屏幕尺寸上按预期工作。怎么编码,不管屏幕大小还是 uilabel fontsize 都能达到一样的效果?

动画 ImageView(3 个点)

  func showAnimatingDotsInImageView(dots: UIImageView)
 
        let newX = view.bounds.width / 896 * 20
        let lay = CAReplicatorLayer()
        lay.frame = CGRect(x: newX,y: 0,width: dots.bounds.width,height: dots.bounds.height)
        let bar = CALayer()
        bar.frame = CGRect(x: 0,y: (dots.bounds.height/2) + 8 ,width: 8,height: 8)  //make the objs smaller or bigger
        bar.cornerRadius = bar.frame.width / 2  //make a circle, if you uncomment this you will get rects
        bar.backgroundColor = UIColor.black.cgColor   //colour of the objs
        lay.addSublayer(bar)
        lay.instanceCount = 3   //How many instances / objs do you want to see
        lay.instanceTransform = CATransform3DMakeTranslation(15, 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)
    
        dots.layer.addSublayer(lay)    // add to the view

        

“从主菜单中检索框”是 UILabel,点在 UIImageView 上进行动画处理

【问题讨论】:

您的屏幕截图是否在标签的右边缘显示UILabelUIImageView @DonMag 是的。 UIImage 在它的右边 【参考方案1】:

您已经很接近了...只需进行一些更改即可到达您想要的位置。

如果您有一个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
    


【讨论】:

感谢您的帮助和详细的代码cmets!我真的学到了很多

以上是关于在 swift iOS 中为 3 个点设置动画的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中为 UIButton 设置动画

在 Swift 中为对象设置动画?

如何在swift中为边框颜色变化设置动画

在 Swift 中为选定的 UIPickerView 行设置动画背景颜色

如何在 swift 中为 UILabel 中的递增数字设置动画

如何在不制作 IBOutlet 的情况下以编程方式在 Swift 中为 UIView 高度约束设置动画?