Câu trả lời:
Trong iOS 4 trở lên, có một cách để làm điều này chỉ bằng cách sử dụng phương thức chuyển đổi UIView mà không cần nhập QuartzCore. Bạn chỉ có thể nói:
[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
})
Giải pháp của Michail sẽ hoạt động, nhưng nó không thực sự là cách tiếp cận tốt nhất.
Vấn đề với alpha fading là đôi khi các lớp khung nhìn chồng chéo khác nhau trông kỳ lạ khi chúng mờ dần. Có một số lựa chọn thay thế khác sử dụng Core Animation. Đầu tiên bao gồm khung QuartzCore trong ứng dụng của bạn và thêm #import <QuartzCore/QuartzCore.h>
vào tiêu đề của bạn. Bây giờ bạn có thể làm một trong những điều sau đây:
1) thiết lập button.layer.shouldRasterize = YES;
và sau đó sử dụng mã hoạt hình alpha mà Michail cung cấp trong câu trả lời của mình. Điều này sẽ ngăn các lớp trộn lẫn một cách kỳ lạ, nhưng có một hiệu suất phạt nhẹ và có thể làm cho nút trông mờ đi nếu nó không được căn chỉnh chính xác trên một ranh giới pixel.
Cách khác:
2) Sử dụng mã sau đây để tạo hiệu ứng mờ dần:
CATransition *animation = [CATransition animation];
animation.type = kCATransitionFade;
animation.duration = 0.4;
[button.layer addAnimation:animation forKey:nil];
button.hidden = YES;
Điều hay ho của cách tiếp cận này là bạn có thể xen kẽ bất kỳ thuộc tính nào của nút ngay cả khi chúng không thể hoạt hình (ví dụ: văn bản hoặc hình ảnh của nút), chỉ cần thiết lập chuyển đổi và sau đó thiết lập các thuộc tính của bạn ngay sau đó.
transitionWithView
tham số để đảm bảo mờ dần thành công.
Thuộc tính hoạt hình của UIView là:
- frame
- bounds
- center
- transform
- alpha
- backgroundColor
- contentStretch
Mô tả trong: Ảnh động
isHidden
không phải là một trong số họ, vì vậy theo tôi thấy cách tốt nhất là:
Swift 4:
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.isHidden = hidden
})
}
Mục tiêu C:
- (void)setView:(UIView*)view hidden:(BOOL)hidden {
[UIView transitionWithView:view duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^(void){
[view setHidden:hidden];
} completion:nil];
}
Để làm mờ dần:
Mục tiêu-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*)
}];
Swift 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
}
Để mờ dần trong:
Mục tiêu-C
button.alpha = 0;
button.hidden = NO;
[UIView animateWithDuration:0.3 animations:^{
button.alpha = 1;
}];
Swift 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
}
Tôi sử dụng tiện ích mở rộng Swift 3 nhỏ này :
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)
}
}
nhanh chóng 4.2
với phần mở rộng:
extension UIView {
func hideWithAnimation(hidden: Bool) {
UIView.transition(with: self, duration: 0.5, options: .transitionCrossDissolve, animations: {
self.isHidden = hidden
})
}
}
phương pháp đơn giản:
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.isHidden = hidden
})
}
Sử dụng giải pháp này để tạo hiệu ứng fadeOut và fadeIn mượt mà
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)
}
}
sử dụng là như thế
uielement.fadeIn()
uielement.fadeOut()
Cảm ơn
fadeOut
chỉ hoạt động trên iOS 13 nếu tôi xóa các dòng đã đặt self.isHidden
.
Tôi đã tạo ra thể loại cho UIView
mục đích này và thực hiện một khái niệm khác biệt nhỏ một chút : visibility
. Sự khác biệt chính của giải pháp của tôi là bạn có thể gọi [view setVisible:NO animated:YES]
và ngay sau đó kiểm tra đồng bộ [view visible]
và nhận được kết quả chính xác. Điều này khá đơn giản nhưng cực kỳ hữu ích.
Ngoài ra, được phép tránh sử dụng "logic boolean âm" (xem Hoàn thành mã, trang 269, Sử dụng tên biến boolean dương để biết thêm thông tin).
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
mã của @Umair Afzal hoạt động tốt trong swift 5 sau một số thay đổi
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)
}
}
}
để sử dụng
yourView.fadeOut()
yourView.fadeIn()
Swift 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)
}
}
}
Và để sử dụng, hãy gọi các hàm này như sau:
yourView.fadeOut() // this will hide your view with animation
yourView.fadeIn() /// this will show your view with animation
isHidden
là một giá trị ngay lập tức và bạn không thể ảnh hưởng đến hình ảnh động trên nó, thay vì điều này bạn có thể sử dụng Alpha để ẩn chế độ xem của mình
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.alpha = 0
})
Và để hiển thị:
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.alpha = 1
})
Bạn có thể làm điều đó RẤT dễ dàng bằng thư viện 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
})
}
Bạn có thể thử điều này.
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)
})
}
Và vượt qua tên xem của bạn
showView(objView: self.viewSaveCard)
HideView(objView: self.viewSaveCard)
Nếu chế độ xem của bạn được đặt thành ẩn theo mặc định hoặc bạn thay đổi trạng thái Ẩn mà tôi nghĩ bạn nên làm trong nhiều trường hợp, thì không có cách tiếp cận nào trong trang này sẽ cung cấp cho bạn cả hoạt hình FadeIn / FadeOut, nó sẽ chỉ làm động một trong những trạng thái này, Lý do là bạn đang đặt trạng thái Ẩn thành sai trước khi gọi UIView.animate phương thức sẽ gây ra khả năng hiển thị đột ngột và nếu bạn chỉ tạo hiệu ứng alpha thì không gian đối tượng vẫn ở đó nhưng nó không hiển thị sẽ dẫn đến một số vấn đề về UI.
Vì vậy, cách tiếp cận tốt nhất là kiểm tra trước xem chế độ xem có bị ẩn hay không, sau đó đặt alpha thành 0,0, như thế này khi bạn đặt trạng thái Ẩn thành sai, bạn sẽ không nhìn thấy tầm nhìn đột ngột.
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)
})
}
Chức năng UIView.transition (với :) rất hay và gọn gàng.
Nhiều người đã đăng nó nhưng không ai nhận thấy rằng có một lỗi sẽ chỉ xuất hiện khi bạn chạy nó.
Bạn có thể chuyển đổi thuộc tính ẩn thành true một cách hoàn hảo, trong khi đó khi bạn cố gắng chuyển nó thành false, chế độ xem sẽ đơn giản biến mất đột ngột mà không có bất kỳ hình ảnh động nào.
Đó là bởi vì api này chỉ hoạt động trong một chế độ xem, có nghĩa là khi bạn chuyển đổi một chế độ xem để hiển thị, trên thực tế, chính nó hiển thị ngay lập tức, chỉ có nội dung của nó hoạt hình dần dần.
Khi bạn cố gắng che giấu quan điểm này, chính nó sẽ ẩn đi ngay lập tức, làm cho hình ảnh động đến nội dung của nó trở nên vô nghĩa.
Để giải quyết vấn đề này, khi ẩn chế độ xem, mục tiêu chuyển đổi phải là chế độ xem chính của nó thay vì chế độ xem bạn muốn ẩn.
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)
}
Giải pháp của tôi cho Swift 3 . Vì vậy, tôi đã tạo hàm, ẩn / bỏ ẩn chế độ xem theo đúng thứ tự (khi ẩn - đặt alpha thành 0 và sau đó được giữ thành đúng; không ẩn - trước tiên hiển thị chế độ xem và sau đó đặt alpha thành 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
khối có một hình ảnh động khác khi hide
là sai?
Chuyển đổi Swift 4
UIView.transition(with: view, duration: 3, options: .transitionCurlDown,
animations: {
// Animations
view.isHidden = hidden
},
completion: { finished in
// Compeleted
})
Nếu bạn sử dụng phương pháp cho các phiên bản nhanh hơn cũ, bạn sẽ gặp lỗi:
Cannot convert value of type '(_) -> ()' to expected argument type '(() -> Void)?'
Tài liệu tham khảo hữu ích .
isHidden
giá trị được trả lại ngay lập tức (ví dụ, ngay lập tức ẩn / hiện xem).
Mã này cung cấp một hình ảnh động như đẩy viewContoder trong bộ điều khiển uinavulation ...
CATransition *animation = [CATransition animation];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromRight;
animation.duration = 0.3;
[_viewAccountName.layer addAnimation:animation forKey:nil];
_viewAccountName.hidden = true;
Được sử dụng cho hoạt hình pop ...
CATransition *animation = [CATransition animation];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromLeft;
animation.duration = 0.3;
[_viewAccountName.layer addAnimation:animation forKey:nil];
_viewAccountName.hidden = false;
Đã thử một số câu trả lời đã thoát, một số chỉ hoạt động cho một tình huống, một số trong số chúng cần thêm hai chức năng.
lựa chọn 1
Không có gì để làm với 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
})
}
}
Sau đó vượt qua isFadeIn
( true
hoặc false
)
view.animate(fadeIn: isFadeIn)
Lựa chọn 2
Đừng vượt qua bất kỳ tham số. Nó mờ dần trong hoặc ra theo isUserInteractionEnabled
. Điều này cũng phù hợp với tình huống animate qua lại rất tốt.
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
})
}
Sau đó, bạn gọi
yourView.animateFadeInOut()
Tại sao
self.isUserInteractionEnabled
?Đã thử để thay thế
self.isUserInteractionEnabled
bởiself.isHidden
, không có may mắn nào cả.
Đó là nó. Đôi khi chi phí cho tôi, hy vọng nó sẽ giúp được ai đó.