Tôi đang đặt một giá trị văn bản mới cho a UILabel
. Hiện tại, văn bản mới xuất hiện tốt. Tuy nhiên, tôi muốn thêm một số hình ảnh động khi văn bản mới xuất hiện. Tôi đang tự hỏi tôi có thể làm gì để làm sinh động sự xuất hiện của văn bản mới.
Tôi đang đặt một giá trị văn bản mới cho a UILabel
. Hiện tại, văn bản mới xuất hiện tốt. Tuy nhiên, tôi muốn thêm một số hình ảnh động khi văn bản mới xuất hiện. Tôi đang tự hỏi tôi có thể làm gì để làm sinh động sự xuất hiện của văn bản mới.
Câu trả lời:
Tôi tự hỏi nếu nó hoạt động, và nó hoạt động hoàn hảo!
Mục tiêu-C
[UIView transitionWithView:self.label
duration:0.25f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.label.text = rand() % 2 ? @"Nice nice!" : @"Well done!";
} completion:nil];
Swift 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)
Để đạt được chuyển đổi hòa tan chéo thực sự (nhãn cũ mờ dần trong khi nhãn mới mờ dần), bạn không muốn mờ dần thành vô hình. Nó sẽ dẫn đến nhấp nháy không mong muốn ngay cả khi văn bản không thay đổi .
Sử dụng phương pháp này thay thế:
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"
Xem thêm: Animate văn bản UILabel giữa hai số?
Trình diễn trong iOS 10, 9, 8:
Đã thử nghiệm với Xcode 8.2.1 & 7.1 , ObjectiveC trên iOS 10 đến 8.0 .
► Để tải xuống toàn bộ dự án, tìm kiếm SO-3073520 trong Swift Recipes .
-addAnimation:forKey
cho nhãn đó, sau đó thay đổi văn bản của nhãn.
Cách thích hợp để làm mờ UILabel (hoặc bất kỳ UIView nào cho vấn đề đó) là sử dụng a Core Animation Transition
. Điều này sẽ không nhấp nháy, cũng sẽ không phai thành màu đen nếu nội dung không thay đổi.
Một giải pháp di động và sạch sẽ là sử dụng Extension
trong Swift (gọi các phần tử hiển thị thay đổi trước đó)
// 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)
}
}
Lời mời trông như thế này:
// This will fade
aLabel.fadeTransition(0.4)
aLabel.text = "text"
► Tìm giải pháp này trên GitHub và các chi tiết bổ sung trên Swift Recipes .
MIT
Giấy phép đó đảm bảo Cocoapod của bạn có thể được sử dụng tự do bởi mọi người và bất cứ ai.
kể từ iOS4, rõ ràng nó có thể được thực hiện với các khối:
[UIView animateWithDuration:1.0
animations:^{
label.alpha = 0.0f;
label.text = newText;
label.alpha = 1.0f;
}];
Đây là mã để làm cho công việc này.
[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];
Giải pháp mở rộng 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)
}
}
Chức năng gọi đơn giản là
uiLabel.textWithAnimation(text: "text you want to replace", duration: 0.2)
Cảm ơn sự hướng dẫn. Hy vọng điều này sẽ giúp lâu dài
Phiên bản Swift 4.2 của giải pháp SwiftArchitect ở trên (hoạt động rất tốt):
// 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)
}
}
Cầu nguyện:
// This will fade
aLabel.fadeTransition(0.4)
aLabel.text = "text"
Swift 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"
})
HOẶC LÀ
UIView.animateWithDuration(0.2, animations: {
self.sampleLabel.alpha = 1
}, completion: {
(value: Bool) in
self.sampleLabel.alpha = 0.2
})
Với Swift 5, bạn có thể chọn một trong hai mẫu mã Playground sau để tạo hiệu ứng UILabel
thay đổi văn bản của bạn với một số hình ảnh động hòa tan chéo.
UIView
là transition(with:duration:options:animations:completion:)
phương pháp lớpimport 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
CATransition
và CALayer
's add(_:forKey:)
phương phápimport 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
Giải pháp Swift 4.2 (lấy câu trả lời 4.0 và cập nhật cho các enum mới để biên dịch)
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"
}
Các giá trị mặc định của hệ thống là 0,25 cho duration
và .curveEaseInEaseOut timingFunction
thường được ưu tiên hơn cho tính nhất quán trong các hình ảnh động và có thể được bỏ qua:
let animation = CATransition()
label.layer.add(animation, forKey: nil)
label.text = "New text"
Điều này giống như viết này:
let animation = CATransition()
animation.duration = 0.25
animation.timingFunction = .curveEaseInEaseOut
label.layer.add(animation, forKey: nil)
label.text = "New text"
Đây là phương thức mở rộng C # UIView dựa trên mã của @ SwiftArchitect. Khi bố trí tự động có liên quan và các điều khiển cần di chuyển tùy thuộc vào văn bản của nhãn, mã gọi này sử dụng Superview của nhãn làm chế độ xem chuyển tiếp thay vì chính nhãn. Tôi đã thêm một biểu thức lambda cho hành động để làm cho nó được gói gọn hơn.
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();
}
Mã gọi:
labelSuperview.FadeTransition( 0.5d, () =>
{
if ( condition )
label.Text = "Value 1";
else
label.Text = "Value 2";
} );
Nếu bạn muốn làm điều này Swift
với sự chậm trễ, hãy thử điều này:
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
})
}
})
}
sử dụng chức năng sau được tạo bởi @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)
}
sẽ trở thành thứ này trong Swift 3
func delay(_ delay:Double, closure:()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.after(when: when, execute: closure)
}
Có một giải pháp nữa để đạt được điều này. Nó đã được mô tả ở đây . Ý tưởng là phân lớp UILabel
và action(for:forKey:)
chức năng ghi đè theo cách sau:
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)
}
}
Ví dụ sử dụng:
// 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!"