• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

支持ObjC的Swift版 UILable文本数值变化效果

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

AnimatingLabel.swift 一种UILable 文本数值变化效果,强大简单实用。具体文件参考如下:

import Foundation
import UIKit

public protocol TextContainable: class {
    var text: String? { get set }
}

public protocol DigitAnimatable: TextContainable {
    
    func animate(to value: Double, duration: Double, formatter: NumberFormatter?, easingOption: EasingOption)
}

public extension DigitAnimatable {
    
    public func animate(to value: Double, duration: Double = 1, formatter: NumberFormatter? = nil, easingOption: EasingOption = .easeInOut) {
        
        let numberFormatter: NumberFormatter
        if let formatter = formatter {
            numberFormatter = formatter
        } else {
            numberFormatter = NumberFormatter()
            numberFormatter.minimumFractionDigits = 2
        }
        
        let text: String = self.text ?? (numberFormatter.string(for: 0) ?? "0")
        
        let number = numberFormatter.number(from: text)?.doubleValue ?? 0
        let diff = value - number
        
        CustomAnimator(duration: duration, easingOption: easingOption, update: { [weak self] progress in
            self?.text = numberFormatter.string(for: number + diff * progress)
            }, completion: {
                self.text = numberFormatter.string(for: value)
        })
    }
}

extension UILabel: DigitAnimatable {}

//MARK: - Implementation
open class CustomAnimator: NSObject {
    private var timer: CADisplayLink?
    
    open private(set) var lastUpdate: TimeInterval
    open private(set) var progress: TimeInterval = 0
    open private(set) var duration: TimeInterval
    
    open var update: ((Double) -> Void)
    open var completion: (() -> Void)?
    
    open private(set) var easingOption: EasingOption
    
    @discardableResult
    public init(duration: TimeInterval, easingOption: EasingOption = .easeInOut, update: @escaping (Double) -> Void, completion: (() -> Void)? = nil) {
        self.lastUpdate = Date.timeIntervalSinceReferenceDate
        self.duration = duration
        self.update = update
        self.easingOption = easingOption
        self.completion = completion
        
        super.init()
        
        self.timer = CADisplayLink(target: self, selector: #selector(CustomAnimator.tick(timer:)))
        if #available(iOS 10.0, *) {
            self.timer?.preferredFramesPerSecond = 60
        } else {
            self.timer?.frameInterval = 1
        }
        self.timer?.add(to: .current, forMode: .common)
        self.timer?.add(to: .current, forMode: .tracking)
        
        self.update(0)
    }
    
    @objc(tick:) open func tick(timer: Timer) {
        let now = Date.timeIntervalSinceReferenceDate
        self.progress += now - self.lastUpdate
        self.lastUpdate = now
        
        if self.progress > self.duration {
            self.timer?.invalidate()
            self.update(1)
            self.timer = nil
            self.completion?()
            return
        }
        
        self.update(self.easingOption.ease(self.progress / self.duration))
    }
    
    /**
     * 数字动画(供ObjC 调用)
     * @param toValue  Double 最终显示的值
     * @param duration Double 动画时间
     */
    @objc(animationLable:toValue:andDuration:) open func animationLable(labInfo:UILabel,toValue value:Double,andDuration duration:Double){
        let labSwift:UILabel? = labInfo;
        labSwift?.animate(to: value,
                          duration: duration,
                          formatter: nil,
                          easingOption: .easeInOut)
    }
}

public enum EasingOption {
    case linear
    case easeIn
    case easeOut
    case easeInOut
}

public extension EasingOption {
    public func ease(_ t: Double) -> Double {
        switch self {
        case .linear:
            return t
        case .easeIn:
            return pow(t, 2)
        case .easeOut:
            return 1.0 - pow(1.0 - t, 2)
        case .easeInOut:
            let sign: Double = -1
            let t = t * 2
            if t < 1 {
                return 0.5 * pow(t, 2)
            } else {
                return sign * 0.5 * (pow(t - 2, 2) + sign * 2)
            }
        }
    }
    
}

Swift 项目中直接使用即可,在ObjC中引入 app名-Swift.h 文件 ,具体操作可参考网络文章,ObjC中 调用方法如下:

    CustomAnimator *customAnimator = [CustomAnimator alloc];
    self.labCurrentInfo.text = @"0.00";//一定要先清理下
    [customAnimator animationLable:self.labCurrentInfo
                           toValue:5000.0 //最终值
                       andDuration:3];    //动画时间,单位秒 

补充:原文作者已不可考,版权归原作者所有,上文中 animationLable 方法是本人后来新增是为了能在ObjC 项目使用,经测试效果杠杠滴,具体效果参见下文图片:


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
[Swift]LeetCode292.Nim游戏|NimGame发布时间:2022-07-13
下一篇:
[Swift]LeetCode1162.地图分析|AsFarfromLandasPossible发布时间:2022-07-13
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap