Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 如何在UILabel中设置递增数字的动画_Iphone_Ios_Xcode_Animation - Fatal编程技术网

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

Iphone 如何在UILabel中设置递增数字的动画,iphone,ios,xcode,animation,Iphone,Ios,Xcode,Animation,我有一个标签显示一个数字,我想把它改成一个更高的数字,不过我想给它添加一点flare。 我想让数字增加到更高的数字,并在输出曲线上变缓,这样它会加速然后变慢。 这个答案显示了如何使它增加(第二个答案,不是公认的答案),但我宁愿动画它,这样我也可以使它的大小略有增加,然后再次缩小,以及缓解inout曲线。 有什么办法可以最好地实现这一点? 谢谢 开始/结束编号将由用户输入,我希望它在相同的时间内增加结束编号。因此,如果我有“开始10结束100”或“开始10结束1000”,我希望它在5秒内计数到结

我有一个标签显示一个数字,我想把它改成一个更高的数字,不过我想给它添加一点flare。 我想让数字增加到更高的数字,并在输出曲线上变缓,这样它会加速然后变慢。 这个答案显示了如何使它增加(第二个答案,不是公认的答案),但我宁愿动画它,这样我也可以使它的大小略有增加,然后再次缩小,以及缓解inout曲线。

有什么办法可以最好地实现这一点? 谢谢


开始/结束编号将由用户输入,我希望它在相同的时间内增加结束编号。因此,如果我有“开始10结束100”或“开始10结束1000”,我希望它在5秒内计数到结束数字。

您可以使用一个标志来查看它是否必须上升或下降。 使用while循环代替for循环。
通过这种方式,您正在创建一个持续运行的循环,因此您必须找到一种方法来停止它,例如通过按下按钮。

我实际上为这个名为UICountingLabel的对象创建了这样一个类:

它允许您指定是希望计数模式为线性、缓进、缓出还是缓进/缓出。“缓进/缓出”开始缓慢计数,加速,然后缓慢结束-所有这些都在您指定的时间内完成


它目前不支持根据当前值设置标签的实际字体大小,不过如果这是一个需要的功能,我可能会添加对该功能的支持。我的布局中的大多数标签都没有太多的空间可以扩展或缩小,所以我不确定您希望如何使用它。但是,它的行为完全类似于普通标签,因此您也可以自己更改字体大小。

您可以使用GCD将延迟转移到后台线程

下面是值动画的示例(10秒内从1到100)

float animationPeriod=10;
调度异步(调度获取全局队列(调度队列优先级高,0)^{
对于(int i=1;i<101;i++){
usleep(animationPeriod/100*1000000);//以微秒为单位睡眠
dispatch\u async(dispatch\u get\u main\u queue()^{
yourLabel.text=[NSString stringWithFormat:@“%d”,i];
});
}
});
我就是这样做的:

- (void)setupAndStartCounter:(CGFloat)duration {
    NSUInteger step = 3;//use your own logic here to define the step.
    NSUInteger remainder = numberYouWantToCount%step;//for me it was 30

    if (step < remainder) {
        remainder = remainder%step;
    }

    self.aTimer = [self getTimer:[self getInvocation:@selector(animateLabel:increment:) arguments:[NSMutableArray arrayWithObjects:[NSNumber numberWithInteger:remainder], [NSNumber numberWithInteger:step], nil]] timeInterval:(duration * (step/(float) numberYouWantToCountTo)) willRepeat:YES];
    [self addTimerToRunLoop:self.aTimer];
}

- (void)animateLabel:(NSNumber*)remainder increment:(NSNumber*)increment {
    NSInteger finish = finalValue;

    if ([self.aLabel.text integerValue] <= (finish) && ([self.aLabel.text integerValue] + [increment integerValue]<= (finish))) {
        self.aLabel.text = [NSString stringWithFormat:@"%lu",(unsigned long)([self.aLabel.text integerValue] + [increment integerValue])];
    }else{
        self.aLabel.text = [NSString stringWithFormat:@"%lu",(unsigned long)([self.aLabel.text integerValue] + [remainder integerValue])];
        [self.aTimer invalidate];
        self.aTimer = nil;
    }
}

#pragma mark -
#pragma mark Timer related Functions

- (NSTimer*)getTimer:(NSInvocation *)invocation timeInterval:(NSTimeInterval)timeInterval willRepeat:(BOOL)willRepeat
{
    return [NSTimer timerWithTimeInterval:timeInterval invocation:invocation repeats:willRepeat];
}

- (NSInvocation*)getInvocation:(SEL)methodName arguments:(NSMutableArray*)arguments
{
    NSMethodSignature *sig = [self methodSignatureForSelector:methodName];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
    [invocation setTarget:self];
    [invocation setSelector:methodName];
    if (arguments != nil)
    {
        id arg1 = [arguments objectAtIndex:0];
        id arg2 = [arguments objectAtIndex:1];
        [invocation setArgument:&arg1 atIndex:2];
        [invocation setArgument:&arg2 atIndex:3];
    }
    return invocation;
}

- (void)addTimerToRunLoop:(NSTimer*)timer
{
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
}
-(无效)设置和开始计数器:(CGFloat)持续时间{
NSUInteger step=3;//在这里使用您自己的逻辑来定义步骤。
NSUInteger余数=numberYouWantToCount%step;//对我来说是30
如果(步骤<余数){
余数=余数%步数;
}
self.aTimer=[self-getTimer:[self-getInvocation:@selector(animateLabel:increment:)参数:[NSMutableArray arrayWithObjects:[NSNumber numberWithInteger:rements],[NSNumber numberWithInteger:step],nil]]时间间隔:(duration*(步长/(float)numberYouWantToCountTo))将重复:YES];
[self addTimerToRunLoop:self.aTimer];
}
-(void)animateLabel:(NSNumber*)余数增量:(NSNumber*)增量{
NSInteger finish=最终值;

如果([self.aLabel.text integerValue]这里是@malex在swift 3中的答案

func incrementLabel(to endValue: Int) {
    let duration: Double = 2.0 //seconds
    DispatchQueue.global().async {
        for i in 0 ..< (endValue + 1) {
            let sleepTime = UInt32(duration/Double(endValue) * 1000000.0)
            usleep(sleepTime)
            DispatchQueue.main.async {
                self.myLabel.text = "\(i)"
            }
        }
    }
}
func incrementLabel(到endValue:Int){
let持续时间:双精度=2.0//s
DispatchQueue.global().async{
对于0中的i.<(endValue+1){
让睡眠时间=UInt32(持续时间/双倍(结束值)*1000000.0)
usleep(睡眠时间)
DispatchQueue.main.async{
self.myLabel.text=“\(i)”
}
}
}
}
但是,我强烈建议您只需将其拖动到您的项目中,我之所以使用它,是因为我的代码中的计时似乎没有针对较低/较高的计数进行适当调整。该类工作非常好,看起来非常好。请参阅以获取参考。

您也可以检查

它允许使用以下代码行递增/递减UILabel中的数字:

[self.label lsAnimateCounterWithStartValue:10 endValue:100 duration:5 completionBlock:nil];
细节 代码9.2,swift 4

解决方案 全样本 不要忘记在此处添加解决方案代码

结果 Swift 4代码:

let animationPeriod: Float = 1
    DispatchQueue.global(qos: .default).async(execute: {
        for i in 1..<Int(endValue) {
            usleep(useconds_t(animationPeriod / 10 * 10000)) // sleep in microseconds
            DispatchQueue.main.async(execute: {
                self.lbl.text = "\(i+1)"
            })
        }
    })
let animationPeriod:Float=1
DispatchQueue.global(qos:.默认值).异步(执行:{

对于1..中的i,如果想要快速计数动画,可以使用如下递归函数:

func updateGems(diff: Int) {
     animateIncrement(diff: diff, index: 0, start: 50)
}

func animateIncrement(diff: Int, index: Int, start: Int) {

    if index == diff {return}
    gemsLabel.text = "\(start + index)"
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.002) {
        self.animateIncrement(diff: diff, index: index + 1, start: start)
    }
}

在这里,你可以不阻塞睡眠! 将其粘贴到UILabel上,它会从当前显示的值向上和向下计数,首先清除非数字。 如果需要,从双精度调整为整数或浮动


对于寻找线性减速计数器(Swift 5)的用户:


您可以根据需要更改静态值,从而更改起点和终点并降低速度;)

也许我解释得不够清楚。我的问题补充了更多。我可以使用for循环或while循环从一个数字增加到另一个数字。但是我希望它通过慢慢加速然后在接近终点时减速来计数。所有这些都在设定的时间内发生。然后你可以使用2个for循环:-一个上升-一个计数down如果你想使用设定的时间量,你必须使用计时器,因为否则,它的发生速度与cpu处理它的速度一样快。我不需要倒计时。我可以管理循环,我只需要在一定的时间量内进行处理。我可以将倒计时循环放在计时器中,使过程在该时间量内发生,就像动画一样?我想计时器会告诉它发生的频率。如果你在问题中发布的链接上看到第一个答案,你可以看到计时器每秒循环15次。你可以使用两个不同时间的循环。另一种方法是使用选项
sleep(毫秒)
在您的循环中。如果您使用一个参数作为等待时间,您可以通过自定义算法来减少它。例如,第一次运行2000毫秒,第二次运行2000毫秒-(i*100毫秒),等等。问题是如果我得到一个很高的数字,我必须数到。我不想减慢它,我想加快它。很高兴您喜欢它:)如果您有任何功能请求,请随时在Github上发布!这是
let loadingProcess = LoadingProcess(minValue: 0, maxValue: 100)

loadingProcess.simulateLoading(toValue: 80, valueChanged: { currentValue in
    // Update views
})

DispatchQueue.global(qos: .background).async {
    print("Start loading data")
    sleep(5)
    print("Data loaded")
    loadingProcess.finish(valueChanged: { currentValue in
        // Update views
    }) { _ in
        print("End")
    }
}
import UIKit

class ViewController: UIViewController {

    weak var counterLabel: UILabel!
    weak var progressView: UIProgressView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let stackView = UIStackView()
        stackView.axis = .vertical
        stackView.alignment = .fill
        stackView.distribution = .fillProportionally
        stackView.spacing = 8
        stackView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stackView)
        stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 80).isActive = true
        stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -80).isActive = true

        let label = UILabel()
        label.textAlignment = .center
        label.text = "0"
        label.font = UIFont.systemFont(ofSize: 46)
        stackView.addArrangedSubview(label)
        counterLabel = label

        let progressView = UIProgressView()
        progressView.trackTintColor = .lightGray
        progressView.progressTintColor = .blue
        progressView.layer.cornerRadius = 4
        progressView.clipsToBounds = true
        progressView.heightAnchor.constraint(equalToConstant: 8).isActive = true
        stackView.addArrangedSubview(progressView)
        self.progressView = progressView

        let button = UIButton()
        button.setTitle("Start", for: .normal)
        button.addTarget(self, action: #selector(startButtonTapped), for: .touchUpInside)
        button.setTitleColor(.blue, for: .normal)
        button.heightAnchor.constraint(equalToConstant: 30).isActive = true
        stackView.addArrangedSubview(button)
    }

    @objc func startButtonTapped() {
        sample()
    }

    private func setProcess(currentValue: Int) {
        let value = 0.01 * Float(currentValue)
        self.counterLabel?.text = "\(currentValue)"
        self.progressView?.setProgress(value, animated: true)
        print("\(currentValue)")
    }

    func sample() {

        let loadingProcess = LoadingProcess(minValue: 0, maxValue: 100)

        loadingProcess.simulateLoading(toValue: 80, valueChanged: { currentValue in
            self.setProcess(currentValue: currentValue)
        })

        DispatchQueue.global(qos: .background).async {
            print("Start loading data")
            sleep(5)
            print("Data loaded")
            loadingProcess.finish(valueChanged: { currentValue in
                self.setProcess(currentValue: currentValue)
            }) { _ in
                print("end")
            }
        }
    }
}
let animationPeriod: Float = 1
    DispatchQueue.global(qos: .default).async(execute: {
        for i in 1..<Int(endValue) {
            usleep(useconds_t(animationPeriod / 10 * 10000)) // sleep in microseconds
            DispatchQueue.main.async(execute: {
                self.lbl.text = "\(i+1)"
            })
        }
    })
func updateGems(diff: Int) {
     animateIncrement(diff: diff, index: 0, start: 50)
}

func animateIncrement(diff: Int, index: Int, start: Int) {

    if index == diff {return}
    gemsLabel.text = "\(start + index)"
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.002) {
        self.animateIncrement(diff: diff, index: index + 1, start: start)
    }
}
yourlabel.countAnimation(upto: 100.0)
another simple alternative

extension UILabel {    
    func countAnimation(upto: Double) {
        let from: Double = text?.replace(string: ",", replacement: ".").components(separatedBy: CharacterSet.init(charactersIn: "-0123456789.").inverted).first.flatMap { Double($0) } ?? 0.0
        let steps: Int = 20
        let duration = 0.350
        let rate = duration / Double(steps)
        let diff = upto - from
        for i in 0...steps {
            DispatchQueue.main.asyncAfter(deadline: .now() + rate * Double(i)) {
                self.text = "\(from + diff * (Double(i) / Double(steps)))"
            }
        }
    }
}
    func animateCountLabel(to userCount: Int) {
        countLabel.text = " "
        let countStart: Int = userCount - 10
        let countEnd: Int = userCount
        DispatchQueue.global(qos: .default).async { [weak self] in
            for i in (countStart...countEnd) {
                let delayTime = UInt64(pow(2, (Float(i) - Float(countStart))))
                usleep(useconds_t( delayTime * 1300 )) // sleep in microseconds
                DispatchQueue.main.async { [weak self] in
                    self?.countLabel.text = "\(i)"
                }
            }
        }
    }