UILabel에서 애니메이션 텍스트 변경


133

새 텍스트 값을로 설정하고 UILabel있습니다. 현재 새 텍스트는 잘 나타납니다. 그러나 새 텍스트가 나타날 때 애니메이션을 추가하고 싶습니다. 새 텍스트의 모양에 애니메이션을 적용하기 위해 무엇을 할 수 있는지 궁금합니다.


Swift 5의 경우 문제를 해결하는 두 가지 방법을 보여주는 내 대답 을 참조하십시오 .
Imanou Petit

답변:


177

그것이 작동하는지 궁금하고 완벽하게 작동합니다!

목표 -C

[UIView transitionWithView:self.label 
                  duration:0.25f 
                   options:UIViewAnimationOptionTransitionCrossDissolve 
                animations:^{

    self.label.text = rand() % 2 ? @"Nice nice!" : @"Well done!";

  } completion:nil];

스위프트 3, 4, 5

UIView.transition(with: label,
              duration: 0.25,
               options: .transitionCrossDissolve,
            animations: { [weak self] in
                self?.label.text = (arc4random()() % 2 == 0) ? "One" : "Two"
         }, completion: nil)

16
TransitionCrossDissolve가이 작업의 핵심입니다.
akaru

7
UIView 애니메이션 블록에는 [약한 자기]가 필요하지 않습니다. 참조 stackoverflow.com/a/27019834/511299
Sunkas

162

목표 -C

진정한 교차 디졸브 전환 ( 새 레이블 페이드 인 동안 이전 레이블 페이드 아웃) 을 달성하려면 페이드가 보이지 않게하고 싶지 않습니다. 그것은 초래 텍스트가 변경되지 않은 경우에도 원치 않는 깜박임 .

대신이 방법을 사용하십시오.

CATransition *animation = [CATransition animation];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.type = kCATransitionFade;
animation.duration = 0.75;
[aLabel.layer addAnimation:animation forKey:@"kCATransitionFade"];

// This will fade:
aLabel.text = "New"

참조 : 애니메이션 UILabel의 텍스트 두 숫자 사이?

iOS 10, 9, 8 시연

공백, 1-5 페이드 전환


테스트 엑스 코드 8.2.1 및 7.1 , 오브젝티브 -c8.0으로 아이폰 OS (10) .

► 전체 프로젝트를 다운로드하려면 Swift Recipes 에서 SO-3073520 을 검색하십시오 .


두 개의 레이블을 동시에 설정하면 시뮬레이터에서 깜박임이 발생합니다.
huggie

1
아마도 오용 되었을까요? 내 접근법의 요점은 2 개의 레이블을 사용하지 않는 것입니다. 단일 레이블을 사용 -addAnimation:forKey하여 해당 레이블에 레이블의 텍스트를 변경하십시오.
SwiftArchitect

@ConfusedVorlon, 진술을 확인하십시오. swiftarchitect.com/recipes/#SO-3073520 에서 게시 된 프로젝트를 확인하십시오 .
SwiftArchitect 오전

과거에 스틱의 끝이 잘못되었을 수 있습니다. 레이어에 대한 전환을 한 번 정의한 다음 후속 변경을 수행하고 '무료'페이드를 얻을 수 있다고 생각했습니다. 각 변경마다 페이드를 지정해야합니다. 따라서 매번 전환을 호출하면 iOS9의 테스트에서 정상적으로 작동합니다.
혼란스러운 볼론

오해의 소지를 제거 하지만 더 이상 적절하지 않다고 생각되면 iOS9에서 작동하지 않는 것 같습니다 . 감사합니다.
SwiftArchitect 2

134

스위프트 4

UILabel (또는 그 문제에 대한 UIView)을 페이드하는 올바른 방법은을 사용하는 것 Core Animation Transition입니다. 내용이 바뀌지 않으면 깜박 거리지 않으며 검은 색으로 사라지지 않습니다.

휴대 가능하고 깨끗한 솔루션은 ExtensionSwift에서 사용하는 것 입니다 (표시 요소를 변경하기 전에 호출)

// Usage: insert view.fadeTransition right before changing content


extension UIView {
    func fadeTransition(_ duration:CFTimeInterval) {
        let animation = CATransition()
        animation.timingFunction = CAMediaTimingFunction(name:
            CAMediaTimingFunctionName.easeInEaseOut)
        animation.type = CATransitionType.fade
        animation.duration = duration
        layer.add(animation, forKey: CATransitionType.fade.rawValue)
    }
}

호출은 다음과 같습니다 :

// This will fade
aLabel.fadeTransition(0.4)
aLabel.text = "text"

공백, 1-5 페이드 전환


GitHub 에서이 솔루션을 찾고 스위프트 레시피 에 대한 추가 세부 사항을 찾으십시오 .


1
안녕 내 프로젝트에서 코드를 사용, 당신이 관심이있을 것이라고 생각 : github.com/goktugyil/CozyLoadingActivity
Esqarrouth

니스-MIT 라이센스 (동일한 라이센스의 변호사 대화 버전)를 사용할 수있는 경우 상용 응용 프로그램에서 사용할 수 있습니다.
SwiftArchitect

라이센스에 대해서는 잘 모르겠습니다. 사람들이 현재 상용 앱에서이를 사용하지 못하게하는 요인은 무엇입니까?
Esqarrouth 2016

2
대부분의 회사는 opensource.org/licenses에 나열되어 있지 않으면 표준 라이센스를 사용할 수 없으며 일부는 opensource.org/licenses/MIT를 준수하는 Cocoapod 만 통합 합니다. 이 MIT라이센스는 Cocoapod를 모든 사람과 누구나 자유롭게 사용할 수 있도록 보장합니다.
SwiftArchitect 2018

2
현재 WTF 라이센스의 문제점은 귀하의 근거를 다루지 않는다는 것입니다. 우선 초보자에게는 귀하를 저자 (저작권)라고 주장하지 않으므로 귀하가 권한을 부여 할 수 없음을 증명합니다. MIT 라이센스에서는 먼저 소유권을 주장한 다음 권리를 포기하는 데 사용합니다. 전문가가 코드를 활용하고 오픈 소스 노력에 참여하기를 원한다면 MIT를 읽어보십시오.
SwiftArchitect

20

iOS4부터 블록으로 분명히 할 수 있습니다.

[UIView animateWithDuration:1.0
                 animations:^{
                     label.alpha = 0.0f;
                     label.text = newText;
                     label.alpha = 1.0f;
                 }];

11
크로스 페이드 전환이 아닙니다.
SwiftArchitect

17

이 작업을 수행하는 코드는 다음과 같습니다.

[UIView beginAnimations:@"animateText" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDuration:1.0f];
[self.lbl setAlpha:0];
[self.lbl setText:@"New Text";
[self.lbl setAlpha:1];
[UIView commitAnimations];

3
이것은 페이드가 아닙니다. 페이드 아웃입니다. 완전히 사라졌다가 페이드 인됩니다. 기본적으로 슬로우 모션 깜박임이지만 여전히 깜박임입니다.
SwiftArchitect

18
UILabels의 이름을 바꾸지 마십시오 lbl
rigdonmr

5

UILabel 확장 솔루션

extension UILabel{

  func animation(typing value:String,duration: Double){
    let characters = value.map { $0 }
    var index = 0
    Timer.scheduledTimer(withTimeInterval: duration, repeats: true, block: { [weak self] timer in
        if index < value.count {
            let char = characters[index]
            self?.text! += "\(char)"
            index += 1
        } else {
            timer.invalidate()
        }
    })
  }


  func textWithAnimation(text:String,duration:CFTimeInterval){
    fadeTransition(duration)
    self.text = text
  }

  //followed from @Chris and @winnie-ru
  func fadeTransition(_ duration:CFTimeInterval) {
    let animation = CATransition()
    animation.timingFunction = CAMediaTimingFunction(name:
        CAMediaTimingFunctionName.easeInEaseOut)
    animation.type = CATransitionType.fade
    animation.duration = duration
    layer.add(animation, forKey: CATransitionType.fade.rawValue)
  }

}

에 의해 간단히 호출 된 기능

uiLabel.textWithAnimation(text: "text you want to replace", duration: 0.2)

모든 팁을 주셔서 감사합니다. 이것이 장기적으로 도움이되기를 바랍니다.


4

위의 SwiftArchitect 솔루션의 Swift 4.2 버전은 훌륭합니다.

    // Usage: insert view.fadeTransition right before changing content    

extension UIView {

        func fadeTransition(_ duration:CFTimeInterval) {
            let animation = CATransition()
            animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
            animation.type = CATransitionType.fade
            animation.duration = duration
            layer.add(animation, forKey: CATransitionType.fade.rawValue)
        }
    }

기도:

    // This will fade

aLabel.fadeTransition(0.4)
aLabel.text = "text"

3

스위프트 2.0 :

UIView.transitionWithView(self.view, duration: 1.0, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: {
    self.sampleLabel.text = "Animation Fade1"
    }, completion: { (finished: Bool) -> () in
        self.sampleLabel.text = "Animation Fade - 34"
})

또는

UIView.animateWithDuration(0.2, animations: {
    self.sampleLabel.alpha = 1
}, completion: {
    (value: Bool) in
    self.sampleLabel.alpha = 0.2
})

1
첫 번째는 작동하지만 두 번째는 통과하는 시간에 관계없이 바로 완료를 호출합니다. 또 다른 문제는 첫 번째 솔루션으로 애니메이션을 적용하는 동안 아무 버튼도 누를 수 없다는 것입니다.
endavid

애니메이션하는 동안 상호 작용을 허용하기 위해 다음 옵션 중 하나를 추가했습니다. [.TransitionCrossDissolve, .AllowUserInteraction]
endavid

self.view를 사용하는 첫 번째 옵션에서 전체보기가 변경되므로 TransitionCrossDissolve 만 사용할 수 있습니다. 대신 "UIView.transitionWithView (self.sampleLabel, duration : 1.0 ...") 텍스트 만 전환하는 것이 좋습니다. 또한 제 경우에는 "..., 완료 : nil)"을 사용하는 것이 좋습니다.
Vitalii

3

Swift 5를 사용하면 UILabel교차 디졸브 애니메이션으로 텍스트 변경 사항 에 애니메이션을 적용하기 위해 다음 두 가지 놀이터 코드 샘플 중 하나를 선택할 수 있습니다 .


#1. 사용 UIViewtransition(with:duration:options:animations:completion:)클래스 메소드

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {

    let label = UILabel()

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = "Car"

        view.backgroundColor = .white
        view.addSubview(label)

        label.translatesAutoresizingMaskIntoConstraints = false
        label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:)))
        view.addGestureRecognizer(tapGesture)
    }

    @objc func toggle(_ sender: UITapGestureRecognizer) {
        let animation = {
            self.label.text = self.label.text == "Car" ? "Plane" : "Car"
        }
        UIView.transition(with: label, duration: 2, options: .transitionCrossDissolve, animations: animation, completion: nil)
    }

}

let controller = ViewController()
PlaygroundPage.current.liveView = controller

# 2. 사용 CATransitionCALayeradd(_:forKey:)방법을

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {

    let label = UILabel()
    let animation = CATransition()

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = "Car"

        animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
        // animation.type = CATransitionType.fade // default is fade
        animation.duration = 2

        view.backgroundColor = .white
        view.addSubview(label)

        label.translatesAutoresizingMaskIntoConstraints = false
        label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:)))
        view.addGestureRecognizer(tapGesture)
    }

    @objc func toggle(_ sender: UITapGestureRecognizer) {
        label.layer.add(animation, forKey: nil) // The special key kCATransition is automatically used for transition animations
        label.text = label.text == "Car" ? "Plane" : "Car"
    }

}

let controller = ViewController()
PlaygroundPage.current.liveView = controller

두 애니메이션 모두 crossDissolve처럼 작동합니다. 어쨌든 그러한 설명적인 답변에 감사드립니다.
Yash Bedi

2

Swift 4.2 솔루션 (4.0 답변 및 컴파일 할 새 열거 형 업데이트)

extension UIView {
    func fadeTransition(_ duration:CFTimeInterval) {
        let animation = CATransition()
        animation.timingFunction = CAMediaTimingFunction(name:
            CAMediaTimingFunctionName.easeInEaseOut)
        animation.type = CATransitionType.fade
        animation.duration = duration
        layer.add(animation, forKey: CATransitionType.fade.rawValue)
    }
}

func updateLabel() {
myLabel.fadeTransition(0.4)
myLabel.text = "Hello World"
}

2

애니메이션의 일관성을 위해 시스템 기본값 0.25 duration및 .curveEaseInEaseOut timingFunction이 선호되는 경우가 많으므로 생략 할 수 있습니다.

let animation = CATransition()
label.layer.add(animation, forKey: nil)
label.text = "New text"

이것은 이것을 쓰는 것과 같습니다 :

let animation = CATransition()
animation.duration = 0.25
animation.timingFunction = .curveEaseInEaseOut
label.layer.add(animation, forKey: nil)
label.text = "New text"

1

@SwiftArchitect의 코드를 기반으로하는 C # UIView 확장 방법입니다. 자동 레이아웃이 포함되고 레이블 텍스트에 따라 컨트롤을 이동해야하는 경우이 호출 코드는 레이블 자체 대신 전환보기로 레이블의 Superview를 사용합니다. 더 캡슐화되도록 작업에 대한 람다 식을 추가했습니다.

public static void FadeTransition( this UIView AView, double ADuration, Action AAction )
{
  CATransition transition = new CATransition();

  transition.Duration = ADuration;
  transition.TimingFunction = CAMediaTimingFunction.FromName( CAMediaTimingFunction.Linear );
  transition.Type = CATransition.TransitionFade;

  AView.Layer.AddAnimation( transition, transition.Type );
  AAction();
}

전화 코드 :

  labelSuperview.FadeTransition( 0.5d, () =>
  {
    if ( condition )
      label.Text = "Value 1";
    else
      label.Text = "Value 2";
  } );

0

Swift지연과 함께이 작업을 수행하려면 다음을 시도하십시오.

delay(1.0) {
        UIView.transitionWithView(self.introLabel, duration: 0.25, options: [.TransitionCrossDissolve], animations: {
            self.yourLabel.text = "2"
            }, completion:  { finished in

                self.delay(1.0) {
                    UIView.transitionWithView(self.introLabel, duration: 0.25, options: [.TransitionCrossDissolve], animations: {
                        self.yourLabel.text = "1"
                        }, completion:  { finished in

                    })
                }

        })
    }

@matt- https : //stackoverflow.com/a/24318861/1982051에 의해 생성 된 다음 기능 사용 :

func delay(delay:Double, closure:()->()) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue(), closure)
}

스위프트 3에서 이것이 될 것입니다

func delay(_ delay:Double, closure:()->()) {
    let when = DispatchTime.now() + delay
    DispatchQueue.main.after(when: when, execute: closure)
}

0

이를 달성하기위한 또 하나의 솔루션이 있습니다. 여기에 설명되어 있습니다 . 아이디어는 다음과 같은 방식으로 함수를 서브 클래 싱 UILabel하고 재정의 action(for:forKey:)합니다.

class LabelWithAnimatedText: UILabel {
    override var text: String? {
        didSet {
            self.layer.setValue(self.text, forKey: "text")
        }
    }

    override func action(for layer: CALayer, forKey event: String) -> CAAction? {
        if event == "text" {
            if let action = self.action(for: layer, forKey: "backgroundColor") as? CAAnimation {
                let transition = CATransition()
                transition.type = kCATransitionFade

                //CAMediatiming attributes
                transition.beginTime = action.beginTime
                transition.duration = action.duration
                transition.speed = action.speed
                transition.timeOffset = action.timeOffset
                transition.repeatCount = action.repeatCount
                transition.repeatDuration = action.repeatDuration
                transition.autoreverses = action.autoreverses
                transition.fillMode = action.fillMode

                //CAAnimation attributes
                transition.timingFunction = action.timingFunction
                transition.delegate = action.delegate

                return transition
            }
        }
        return super.action(for: layer, forKey: event)
    }
}

사용 예 :

// do not forget to set the "Custom Class" IB-property to "LabelWithAnimatedText"
// @IBOutlet weak var myLabel: LabelWithAnimatedText!
// ...

UIView.animate(withDuration: 0.5) {
    myLabel.text = "I am animated!"
}
myLabel.text = "I am not animated!"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.