Jawaban:
Di iOS 4 dan yang lebih baru, ada cara untuk melakukan ini hanya dengan menggunakan metode transisi UIView tanpa perlu mengimpor QuartzCore. Anda bisa mengatakan:
[UIView transitionWithView:button
duration:0.4
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
button.hidden = YES;
}
completion:NULL];
UIView.transition(with: button, duration: 0.4,
options: .transitionCrossDissolve,
animations: {
button.hidden = false
})
Solusi Michail akan berhasil, tetapi itu sebenarnya bukan pendekatan terbaik.
Masalah dengan alpha fading adalah kadang-kadang lapisan tampilan yang tumpang tindih yang berbeda terlihat aneh saat mereka memudar. Ada beberapa alternatif lain menggunakan Core Animation. Pertama, sertakan kerangka kerja QuartzCore di aplikasi Anda dan tambahkan #import <QuartzCore/QuartzCore.h>
ke tajuk Anda. Sekarang Anda dapat melakukan salah satu dari yang berikut:
1) atur button.layer.shouldRasterize = YES;
dan kemudian gunakan kode animasi alfa yang diberikan Michail dalam jawabannya. Ini akan mencegah lapisan dari campuran aneh, tetapi memiliki penalti kinerja yang sedikit, dan dapat membuat tombol terlihat buram jika tidak selaras tepat pada batas piksel.
Kalau tidak:
2) Gunakan kode berikut untuk menghidupkan fade sebagai gantinya:
CATransition *animation = [CATransition animation];
animation.type = kCATransitionFade;
animation.duration = 0.4;
[button.layer addAnimation:animation forKey:nil];
button.hidden = YES;
Yang menyenangkan tentang pendekatan ini adalah Anda dapat melakukan crossfade properti apa pun dari tombol meskipun mereka tidak dapat digerakkan (mis. Teks atau gambar tombol), cukup atur transisi dan kemudian atur properti Anda segera setelahnya.
transitionWithView
parameter untuk memastikan keberhasilan memudar dan keluar.
Properti animasi UIView adalah:
- frame
- bounds
- center
- transform
- alpha
- backgroundColor
- contentStretch
Jelaskan dalam: Animasi
isHidden
bukan salah satu dari mereka, jadi seperti yang saya lihat, cara terbaik adalah:
Swift 4:
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.isHidden = hidden
})
}
Sasaran C:
- (void)setView:(UIView*)view hidden:(BOOL)hidden {
[UIView transitionWithView:view duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^(void){
[view setHidden:hidden];
} completion:nil];
}
Untuk menghilang:
Objektif-C
[UIView animateWithDuration:0.3 animations:^{
button.alpha = 0;
} completion: ^(BOOL finished) {//creates a variable (BOOL) called "finished" that is set to *YES* when animation IS completed.
button.hidden = finished;//if animation is finished ("finished" == *YES*), then hidden = "finished" ... (aka hidden = *YES*)
}];
Cepat 2
UIView.animateWithDuration(0.3, animations: {
button.alpha = 0
}) { (finished) in
button.hidden = finished
}
Swift 3, 4, 5
UIView.animate(withDuration: 0.3, animations: {
button.alpha = 0
}) { (finished) in
button.isHidden = finished
}
Untuk memudar di:
Objektif-C
button.alpha = 0;
button.hidden = NO;
[UIView animateWithDuration:0.3 animations:^{
button.alpha = 1;
}];
Cepat 2
button.alpha = 0
button.hidden = false
UIView.animateWithDuration(0.3) {
button.alpha = 1
}
Swift 3, 4, 5
button.alpha = 0
button.isHidden = false
UIView.animate(withDuration: 0.3) {
button.alpha = 1
}
Saya menggunakan ekstensi Swift 3 kecil ini :
extension UIView {
func fadeIn(duration: TimeInterval = 0.5,
delay: TimeInterval = 0.0,
completion: @escaping ((Bool) -> Void) = {(finished: Bool) -> Void in }) {
UIView.animate(withDuration: duration,
delay: delay,
options: UIViewAnimationOptions.curveEaseIn,
animations: {
self.alpha = 1.0
}, completion: completion)
}
func fadeOut(duration: TimeInterval = 0.5,
delay: TimeInterval = 0.0,
completion: @escaping (Bool) -> Void = {(finished: Bool) -> Void in }) {
UIView.animate(withDuration: duration,
delay: delay,
options: UIViewAnimationOptions.curveEaseIn,
animations: {
self.alpha = 0.0
}, completion: completion)
}
}
cepat 4.2
dengan ekstensi:
extension UIView {
func hideWithAnimation(hidden: Bool) {
UIView.transition(with: self, duration: 0.5, options: .transitionCrossDissolve, animations: {
self.isHidden = hidden
})
}
}
metode sederhana:
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.isHidden = hidden
})
}
Gunakan solusi ini untuk efek fadeOut dan fadeIn yang halus
extension UIView {
func fadeIn(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping ((Bool) -> Void) = {(finished: Bool) -> Void in }) {
self.alpha = 0.0
UIView.animate(withDuration: duration, delay: delay, options: UIView.AnimationOptions.curveEaseIn, animations: {
self.isHidden = false
self.alpha = 1.0
}, completion: completion)
}
func fadeOut(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping (Bool) -> Void = {(finished: Bool) -> Void in }) {
self.alpha = 1.0
UIView.animate(withDuration: duration, delay: delay, options: UIView.AnimationOptions.curveEaseOut, animations: {
self.isHidden = true
self.alpha = 0.0
}, completion: completion)
}
}
penggunaannya seperti
uielement.fadeIn()
uielement.fadeOut()
Terima kasih
fadeOut
bekerja di iOS 13 hanya jika saya menghapus garis yang ditetapkan self.isHidden
.
Aku menciptakan kategori UIView
untuk tujuan ini dan menerapkan sedikit khusus menggigit konsep yang berbeda: visibility
. Perbedaan utama dari solusi saya adalah Anda dapat menelepon [view setVisible:NO animated:YES]
dan segera setelah itu memeriksa [view visible]
dan mendapatkan hasil yang benar. Ini cukup sederhana tetapi sangat bermanfaat.
Selain itu, diperbolehkan untuk menghindari menggunakan "logika boolean negatif" (lihat Kode Lengkap, halaman 269, Gunakan nama variabel boolean positif untuk informasi lebih lanjut).
UIView+Visibility.swift
import UIKit
private let UIViewVisibilityShowAnimationKey = "UIViewVisibilityShowAnimationKey"
private let UIViewVisibilityHideAnimationKey = "UIViewVisibilityHideAnimationKey"
private class UIViewAnimationDelegate: NSObject {
weak var view: UIView?
dynamic override func animationDidStop(animation: CAAnimation, finished: Bool) {
guard let view = self.view where finished else {
return
}
view.hidden = !view.visible
view.removeVisibilityAnimations()
}
}
extension UIView {
private func removeVisibilityAnimations() {
self.layer.removeAnimationForKey(UIViewVisibilityShowAnimationKey)
self.layer.removeAnimationForKey(UIViewVisibilityHideAnimationKey)
}
var visible: Bool {
get {
return !self.hidden && self.layer.animationForKey(UIViewVisibilityHideAnimationKey) == nil
}
set {
let visible = newValue
guard self.visible != visible else {
return
}
let animated = UIView.areAnimationsEnabled()
self.removeVisibilityAnimations()
guard animated else {
self.hidden = !visible
return
}
self.hidden = false
let delegate = UIViewAnimationDelegate()
delegate.view = self
let animation = CABasicAnimation(keyPath: "opacity")
animation.fromValue = visible ? 0.0 : 1.0
animation.toValue = visible ? 1.0 : 0.0
animation.fillMode = kCAFillModeForwards
animation.removedOnCompletion = false
animation.delegate = delegate
self.layer.addAnimation(animation, forKey: visible ? UIViewVisibilityShowAnimationKey : UIViewVisibilityHideAnimationKey)
}
}
func setVisible(visible: Bool, animated: Bool) {
let wereAnimationsEnabled = UIView.areAnimationsEnabled()
if wereAnimationsEnabled != animated {
UIView.setAnimationsEnabled(animated)
defer { UIView.setAnimationsEnabled(!animated) }
}
self.visible = visible
}
}
UIView+Visibility.h
#import <UIKit/UIKit.h>
@interface UIView (Visibility)
- (BOOL)visible;
- (void)setVisible:(BOOL)visible;
- (void)setVisible:(BOOL)visible animated:(BOOL)animated;
@end
UIView+Visibility.m
#import "UIView+Visibility.h"
NSString *const UIViewVisibilityAnimationKeyShow = @"UIViewVisibilityAnimationKeyShow";
NSString *const UIViewVisibilityAnimationKeyHide = @"UIViewVisibilityAnimationKeyHide";
@implementation UIView (Visibility)
- (BOOL)visible
{
if (self.hidden || [self.layer animationForKey:UIViewVisibilityAnimationKeyHide]) {
return NO;
}
return YES;
}
- (void)setVisible:(BOOL)visible
{
[self setVisible:visible animated:NO];
}
- (void)setVisible:(BOOL)visible animated:(BOOL)animated
{
if (self.visible == visible) {
return;
}
[self.layer removeAnimationForKey:UIViewVisibilityAnimationKeyShow];
[self.layer removeAnimationForKey:UIViewVisibilityAnimationKeyHide];
if (!animated) {
self.alpha = 1.f;
self.hidden = !visible;
return;
}
self.hidden = NO;
CGFloat fromAlpha = visible ? 0.f : 1.f;
CGFloat toAlpha = visible ? 1.f : 0.f;
NSString *animationKey = visible ? UIViewVisibilityAnimationKeyShow : UIViewVisibilityAnimationKeyHide;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.duration = 0.25;
animation.fromValue = @(fromAlpha);
animation.toValue = @(toAlpha);
animation.delegate = self;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[self.layer addAnimation:animation forKey:animationKey];
}
#pragma mark - CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished
{
if ([[self.layer animationForKey:UIViewVisibilityAnimationKeyHide] isEqual:animation]) {
self.hidden = YES;
}
}
@end
kode @Umair Afzal bekerja dengan baik di swift 5 setelah beberapa perubahan
extension UIView {
func fadeIn(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping ((Bool) -> Void) = {(finished: Bool) -> Void in }) {
self.alpha = 0.0
UIView.animate(withDuration: duration, delay: delay, options: UIView.AnimationOptions.curveEaseIn, animations: {
self.isHidden = false
self.alpha = 1.0
}, completion: completion)
}
func fadeOut(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping (Bool) -> Void = {(finished: Bool) -> Void in }) {
self.alpha = 1.0
UIView.animate(withDuration: duration, delay: delay, options: UIView.AnimationOptions.curveEaseIn, animations: {
self.alpha = 0.0
}) { (completed) in
self.isHidden = true
completion(true)
}
}
}
untuk digunakan
yourView.fadeOut()
yourView.fadeIn()
Cepat 4
extension UIView {
func fadeIn(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping ((Bool) -> Void) = {(finished: Bool) -> Void in }) {
self.alpha = 0.0
UIView.animate(withDuration: duration, delay: delay, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.isHidden = false
self.alpha = 1.0
}, completion: completion)
}
func fadeOut(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping (Bool) -> Void = {(finished: Bool) -> Void in }) {
self.alpha = 1.0
UIView.animate(withDuration: duration, delay: delay, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.alpha = 0.0
}) { (completed) in
self.isHidden = true
completion(true)
}
}
}
Dan untuk menggunakannya, panggil fungsi-fungsi ini seperti:
yourView.fadeOut() // this will hide your view with animation
yourView.fadeIn() /// this will show your view with animation
isHidden
adalah nilai langsung dan Anda tidak dapat mempengaruhi animasi di atasnya, alih-alih ini Anda dapat menggunakan Alpha untuk menyembunyikan tampilan Anda
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.alpha = 0
})
Dan untuk menunjukkan:
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.alpha = 1
})
Anda dapat melakukannya dengan SANGAT mudah menggunakan perpustakaan Animatics :
//To hide button:
AlphaAnimator(0) ~> button
//to show button
AlphaAnimator(1) ~> button
func flipViews(fromView: UIView, toView: UIView) {
toView.frame.origin.y = 0
self.view.isUserInteractionEnabled = false
UIView.transition(from: fromView, to: toView, duration: 0.5, options: .transitionFlipFromLeft, completion: { finished in
fromView.frame.origin.y = -900
self.view.isUserInteractionEnabled = true
})
}
Anda bisa mencoba ini.
func showView(objView:UIView){
objView.alpha = 0.0
UIView.animate(withDuration: 0.5, animations: {
objView.alpha = 0.0
}, completion: { (completeFadein: Bool) -> Void in
objView.alpha = 1.0
let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionFade
objView.layer.add(transition, forKey: nil)
})
}
func HideView(objView:UIView){
UIView.animate(withDuration: 0.5, animations: {
objView.alpha = 1.0
}, completion: { (completeFadein: Bool) -> Void in
objView.alpha = 0.0
let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionFade
objView.layer.add(transition, forKey: nil)
})
}
Dan berikan nama tampilan Anda
showView(objView: self.viewSaveCard)
HideView(objView: self.viewSaveCard)
Jika tampilan Anda disetel ke tersembunyi secara default atau Anda mengubah status Tersembunyi yang menurut saya harus Anda lakukan dalam banyak kasus, maka tidak ada pendekatan di halaman ini yang akan memberi Anda animasi FadeIn / FadeOut, itu hanya akan menganimasikan salah satu dari status ini, alasannya adalah Anda mengatur status Tersembunyi ke false sebelum memanggil metode UIView.animate yang akan menyebabkan visibilitas mendadak dan jika Anda hanya menghidupkan alpha maka ruang objek masih ada tetapi tidak terlihat yang akan mengakibatkan beberapa masalah UI.
Jadi pendekatan terbaik adalah memeriksa dulu jika tampilan disembunyikan lalu atur alpha menjadi 0,0, seperti ini saat Anda mengatur status Tersembunyi menjadi false Anda tidak akan melihat visibilitas mendadak.
func hideViewWithFade(_ view: UIView) {
if view.isHidden {
view.alpha = 0.0
}
view.isHidden = false
UIView.animate(withDuration: 0.3, delay: 0.0, options: .transitionCrossDissolve, animations: {
view.alpha = view.alpha == 1.0 ? 0.0 : 1.0
}, completion: { _ in
view.isHidden = !Bool(truncating: view.alpha as NSNumber)
})
}
Fungsi UIView.transition (with :) bagus dan rapi.
Banyak yang mempostingnya tetapi tidak ada yang menyadari bahwa ada kesalahan yang akan muncul hanya ketika Anda menjalankannya.
Anda dapat mentransisikan properti tersembunyi ke true dengan sempurna, sedangkan saat Anda mencoba mengalihkannya ke false, tampilan akan menghilang secara tiba-tiba tanpa animasi.
Itu karena api ini hanya berfungsi dalam tampilan, yang berarti ketika Anda mentransisikan tampilan untuk ditampilkan, sebenarnya itu langsung ditampilkan, hanya kontennya yang keluar secara bertahap.
Ketika Anda mencoba untuk menyembunyikan tampilan ini, itu sendiri bersembunyi segera, membuat animasi menjadi isinya tidak berarti.
Untuk mengatasi ini, saat menyembunyikan tampilan, target transisi haruslah tampilan induknya, bukan tampilan yang ingin Anda sembunyikan.
func transitionView(_ view: UIView?, show: Bool, completion: BoolFunc? = nil) {
guard let view = view, view.isHidden == show, let parent = view.superview else { return }
let target: UIView = show ? view : parent
UIView.transition(with: target, duration: 0.4, options: [.transitionCrossDissolve], animations: {
view.isHidden = !show
}, completion: completion)
}
Solusi saya untuk Swift 3 . Jadi, saya membuat fungsi, yang menyembunyikan / menyembunyikan tampilan dalam urutan yang benar (ketika menyembunyikan - set alpha ke 0 dan kemudian IsHidden ke true; unhiding - pertama mengungkapkan view dan kemudian mengatur alpha ke 1):
func hide(_ hide: Bool) {
let animations = hide ? { self.alpha = 0 } :
{ self.isHidden = false }
let completion: (Bool) -> Void = hide ? { _ in self.isHidden = true } :
{ _ in UIView.animate(withDuration: duration, animations: { self.alpha = 1 }) }
UIView.animate(withDuration: duration, animations: animations, completion: completion)
}
completion
blok ada animasi lain ketika hide
itu salah?
Swift 4 Transition
UIView.transition(with: view, duration: 3, options: .transitionCurlDown,
animations: {
// Animations
view.isHidden = hidden
},
completion: { finished in
// Compeleted
})
Jika Anda menggunakan pendekatan untuk versi cepat swift Anda akan mendapatkan kesalahan:
Cannot convert value of type '(_) -> ()' to expected argument type '(() -> Void)?'
Referensi yang berguna .
isHidden
nilai diberikan langsung (yaitu, langsung bersembunyi / menampilkan tampilan).
Kode ini memberikan animasi seperti mendorong viewController di pengontrol navigasi ...
CATransition *animation = [CATransition animation];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromRight;
animation.duration = 0.3;
[_viewAccountName.layer addAnimation:animation forKey:nil];
_viewAccountName.hidden = true;
Digunakan ini untuk animasi pop ...
CATransition *animation = [CATransition animation];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromLeft;
animation.duration = 0.3;
[_viewAccountName.layer addAnimation:animation forKey:nil];
_viewAccountName.hidden = false;
Mencoba beberapa jawaban yang keluar, beberapa hanya berfungsi untuk satu situasi, beberapa dari mereka perlu menambahkan dua fungsi.
Pilihan 1
Tidak ada hubungannya dengan view.isHidden
.
extension UIView {
func animate(fadeIn: Bool, withDuration: TimeInterval = 1.0) {
UIView.animate(withDuration: withDuration, delay: 0.0, options: .curveEaseInOut, animations: {
self.alpha = fadeIn ? 1.0 : 0.0
})
}
}
Kemudian lulus isFadeIn
( true
atau false
)
view.animate(fadeIn: isFadeIn)
pilihan 2
Jangan melewati parameter apa pun. Itu memudar masuk atau keluar menurut isUserInteractionEnabled
. Ini juga cocok dengan situasi menghidupkan dan bolak-balik dengan sangat baik.
func animateFadeInOut(withDuration: TimeInterval = 1.0) {
self.isUserInteractionEnabled = !self.isUserInteractionEnabled
UIView.animate(withDuration: withDuration, delay: 0.0, options: .curveEaseInOut, animations: {
self.alpha = self.isUserInteractionEnabled ? 1.0 : 0.0
})
}
Lalu kamu menelepon
yourView.animateFadeInOut()
Mengapa
self.isUserInteractionEnabled
?Mencoba untuk mengganti
self.isUserInteractionEnabled
denganself.isHidden
, tidak beruntung sama sekali.
Itu dia. Biaya saya kapan saja, semoga membantu seseorang.