番号を示すラベルがあり、それをより高い番号に変更したいのですが、少しフレアを追加したいと思います。速度を上げてから遅くするために、イージーインアウトカーブを使用して、数値をより高い数値まで増やしたいと思います。この答えは、それを増分する方法を示しています(受け入れられた答えではなく、2番目の答え)が、アニメーション化して、サイズを少し大きくしてから再び縮めるようにするだけでなく、イージングインアウトカーブもできます。 iPhone SDKでランニングスコアアニメーションを行う方法
これを達成する最善の方法はありますか?ありがとう
開始/終了番号はユーザーが入力するので、同じ時間内に終了番号を増やしてほしい。したがって、開始10終了100または開始10終了1000がある場合、5秒で終了番号までカウントするようにします。
フラグを使用して、上下する必要があるかどうかを確認できます。 forループの代わりに、whileループを使用します。このように、あなたは継続して行くループを作成しているので、それを停止する方法も見つける必要があります。ボタンを押す。
実際に、UICountingLabelと呼ばれるこのためのクラスを作成しました。
http://github.com/dataxpress/UICountingLabel
カウントモードを線形、イーズイン、イーズアウト、イーズイン/アウトのいずれにするかを指定できます。イーズイン/アウトは、ゆっくりとカウントを開始し、スピードアップし、ゆっくりと終了します-すべて指定した時間になります。
現在、現在の値に基づいてラベルの実際のフォントサイズを設定することはサポートしていませんが、必要な機能である場合はサポートを追加できます。私のレイアウトのほとんどのラベルには、拡大または縮小する余地があまりないため、どのように使用するのかわかりません。ただし、通常のラベルとまったく同じように動作するため、独自にフォントサイズを変更することもできます。
GCDを使用して、遅延をバックグラウンドスレッドにシフトできます。
バリューアニメーションの例(10秒で1から100)
float animationPeriod = 10;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
for (int i = 1; i < 101; i ++) {
usleep(animationPeriod/100 * 1000000); // sleep in microseconds
dispatch_async(dispatch_get_main_queue(), ^{
yourLabel.text = [NSString stringWithFormat:@"%d", i];
});
}
});
ここでSwift 3.の@malexの答え.
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)"
}
}
}
}
ただし、単純に GitHubからこのクラスをダウンロードする を強くお勧めします。プロジェクトにドラッグします。コードのタイミングがカウントの増減に適切に調整されていないようであるため、使用することに頼りました。数字。このクラスはうまく機能し、見た目もとても良いです。 この中記事 を参照してください。
Swift 4コード
let animationPeriod: Float = 1
DispatchQueue.global(qos: .default).async(execute: {
for i in 1..<10000)! {
usleep(useconds_t(animationPeriod / 10 * 10000)) // sleep in microseconds
DispatchQueue.main.async(execute: {
self.lblCounter.text = "\(i)"
})
}
})
Xcode 9.2、Swift 4
class LoadingProcess {
let minValue: Int
let maxValue: Int
var currentValue: Int
private let progressQueue = DispatchQueue(label: "ProgressView")
private let semaphore = DispatchSemaphore(value: 1)
init (minValue: Int, maxValue: Int) {
self.minValue = minValue
self.currentValue = minValue
self.maxValue = maxValue
}
private func delay(stepDelayUsec: useconds_t, completion: @escaping ()->()) {
usleep(stepDelayUsec)
DispatchQueue.main.async {
completion()
}
}
func simulateLoading(toValue: Int, step: Int = 1, stepDelayUsec: useconds_t? = 10_000,
valueChanged: @escaping (_ currentValue: Int)->(),
completion: ((_ currentValue: Int)->())? = nil) {
semaphore.wait()
progressQueue.sync {
if currentValue <= toValue && currentValue <= maxValue {
usleep(stepDelayUsec!)
DispatchQueue.main.async {
valueChanged(self.currentValue)
self.currentValue += step
self.semaphore.signal()
self.simulateLoading(toValue: toValue, step: step, stepDelayUsec: stepDelayUsec, valueChanged: valueChanged, completion: completion)
}
} else {
self.semaphore.signal()
completion?(currentValue)
}
}
}
func finish(step: Int = 1, stepDelayUsec: useconds_t? = 10_000,
valueChanged: @escaping (_ currentValue: Int)->(),
completion: ((_ currentValue: Int)->())? = nil) {
simulateLoading(toValue: maxValue, step: step, stepDelayUsec: stepDelayUsec, valueChanged: valueChanged, completion: completion)
}
}
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")
}
}
}
}
これは私がそれをやった方法です:
- (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];
}
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)"
})
}
})
https://github.com/leszek-s/LSCategories も確認できます
次のような1行のコードで、UILabelで数値をインクリメント/デクリメントできます。
[self.label lsAnimateCounterWithStartValue:10 endValue:100 duration:5 completionBlock:nil];