UIView Hide/Show с анимацией

Моя простая цель - скрывать скрытые и отображаемые функции.

Button.hidden = YES;

Прост достаточно. Однако возможно ли, чтобы оно исчезло, а не просто исчезло? Это выглядит довольно непрофессионально.

Ответ 1

В iOS 4 и более поздних версиях есть способ сделать это, используя метод перехода UIView без необходимости импортировать QuartzCore. Вы можете просто сказать:

[UIView transitionWithView:button
                  duration:0.4
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                     button.hidden = YES;
                }
                completion:NULL];

Предыдущее решение

Решение Michail будет работать, но на самом деле это не лучший подход.

Проблема с альфа-замиранием заключается в том, что иногда разные перекрывающиеся слои выглядят странно, когда они исчезают. Существуют и другие альтернативы, использующие Core Animation. Сначала включите среду QuartzCore в ваше приложение и добавьте #import <QuartzCore/QuartzCore.h> в свой заголовок. Теперь вы можете выполнить одно из следующих действий:

1) установите button.layer.shouldRasterize = YES;, а затем используйте код альфа-анимации, который был предоставлен Михаилом в его ответе. Это предотвратит странное смешение слоев, но имеет небольшое ограничение производительности и может заставить кнопку выглядеть размытой, если она не выровнена точно на границе пикселя.

В качестве альтернативы:

2) Используйте следующий код для анимирования затухания:

CATransition *animation = [CATransition animation];
animation.type = kCATransitionFade;
animation.duration = 0.4;
[button.layer addAnimation:animation forKey:nil];

button.hidden = YES;

Самое приятное в этом подходе - вы можете перечеркнуть любое свойство кнопки, даже если они не являются анимированными (например, текст или изображение кнопки), просто настройте переход, а затем сразу установите свои свойства.

Ответ 2

Анимированные свойства UIView:

- frame
- bounds
- center
- transform
- alpha
- backgroundColor
- contentStretch

Опишите в: Анимации

isHidden не является одним из них, поэтому, на мой isHidden лучший способ это:

Свифт 4:

func setView(view: UIView, hidden: Bool) {
    UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
        view.isHidden = hidden
    })
}

Цель C:

- (void)setView:(UIView*)view hidden:(BOOL)hidden {
    [UIView transitionWithView:view duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^(void){
        [view setHidden:hidden];
    } completion:nil];
}

Ответ 3

Чтобы исчезнуть:

[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:
UIView.animateWithDuration(0.3, animations: {
    button.alpha = 0
}) { (finished) in
    button.hidden = finished
}

Затухать в:

button.alpha = 0;
button.hidden = NO;
[UIView animateWithDuration:0.3 animations:^{
    button.alpha = 1;
}];

// swift:
button.alpha = 0
button.hidden = false
UIView.animateWithDuration(0.3) {
    button.alpha = 1
}

Ответ 4

Я использую это небольшое расширение Swift 3:

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)
  }
}

Ответ 5

Swift 3

func appearView() {
     self.myView.alpha = 0
     self.myView.isHidden = false

     UIView.animate(withDuration: 0.9, animations: {
         self.myView.alpha = 1
     }, completion: {
         finished in
         self.myView.isHidden = false
     })
}

Ответ 6

Я создал для этой категории категорию UIView и реализовал специальную немного другую концепцию: visibility. Основное отличие моего решения заключается в том, что вы можете вызвать [view setVisible:NO animated:YES] и сразу после этого синхронно проверить [view visible] и получить правильный результат. Это довольно просто, но очень полезно.

Кроме того, разрешено избегать использования "отрицательной логической логики" (см. Code Complete, стр. 269, Использовать логические имена переменных boolean для более информация).

Swift

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
    }

}

Objective-C

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

Ответ 7

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)
    }
}
}

И чтобы использовать его, просто вызовите эти функции, такие как:

yourView.fadeOut() // this will hide your view with animation
yourView.fadeIn() /// this will show your view with animation

Ответ 8

Swift 4.2

с расширением:

extension UIView {
func hideWithAnimation(hidden: Bool) {
        UIView.transition(with: self, duration: 0.5, options: .transitionCrossDissolve, animations: {
            self.isHidden = hidden
        })
    }
}

простой метод:

func setView(view: UIView, hidden: Bool) {
    UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
        view.isHidden = hidden
    })
}

Ответ 9

Код @Umair Afzal работает хорошо в Swift 5 после некоторых изменений

 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)
    }
  }
}

для использования

yourView.fadeOut()
yourView.fadeIn()

Ответ 10

Вы можете сделать это ОЧЕНЬ легко, используя Animatics библиотека:

//To hide button:
AlphaAnimator(0) ~> button

//to show button
AlphaAnimator(1) ~> button

Ответ 11

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

    })


}

Ответ 12

Вы можете попробовать это.

 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)
    })
}

И передайте имя вашего взгляда

        showView(objView: self.viewSaveCard)
        HideView(objView: self.viewSaveCard)

Ответ 13

Мое решение для Swift 3. Таким образом, я создал функцию, которая скрывает/скрывает представление в правильном порядке (при укрытии - устанавливает альфа-значение в 0, а затем isHidden для истины; unhiding - сначала открывает представление, а затем устанавливает альфа-значение в 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)
}

Ответ 14

Swift 4 Transition

    UIView.transition(with: view, duration: 3, options: .transitionCurlDown,
                      animations: {
                        // Animations
                        view.isHidden = hidden
    },
                      completion: { finished in
                        // Compeleted
    })

Если вы используете подход для более старых версий, вы получите сообщение об ошибке:

Cannot convert value of type '(_) -> ()' to expected argument type '(() -> Void)?'

Полезно ссылка.

Ответ 15

Этот код дает анимацию, как нажатие viewController в контроллере uinavigation...

CATransition *animation = [CATransition animation];
 animation.type = kCATransitionPush;
 animation.subtype = kCATransitionFromRight;
 animation.duration = 0.3;
 [_viewAccountName.layer addAnimation:animation forKey:nil];

 _viewAccountName.hidden = true;

Использовал это для поп-анимации...

 CATransition *animation = [CATransition animation];
 animation.type = kCATransitionPush;
 animation.subtype = kCATransitionFromLeft;
 animation.duration = 0.3;
 [_viewAccountName.layer addAnimation:animation forKey:nil];

 _viewAccountName.hidden = false;

Ответ 16

Пробовал некоторые из вышедших ответов, некоторые работают только для одной ситуации, некоторые из них должны добавить две функции.

Опция 1

Ничего общего с 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
        })
    }
}

Затем передайте isFadeIn (true или false)

view.animate(fadeIn: isFadeIn) 

Вариант 2

Не передавайте никаких параметров. Это исчезает или исчезает согласно isUserInteractionEnabled. Это также очень хорошо подходит для анимации ситуации.

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
    })
}

Тогда вы звоните

yourView.animateFadeInOut()

Почему self.isUserInteractionEnabled?

Пытался заменить self.isUserInteractionEnabled на self.isHidden, не повезло вообще.

Это. Стоит мне когда-нибудь, надеюсь, это кому-нибудь поможет.

Ответ 17

Используйте это решение для плавного эффекта fadeOut и fadeIn

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)
    }
}

использование как

uielement.fadeIn()
uielement.fadeOut()

Спасибо

Ответ 18

isHidden является непосредственным значением, и вы не можете влиять на анимацию, вместо этого вы можете использовать Alpha для скрытия вашего вида

UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
        view.alpha = 0
    })

И для показа:

UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
      view.alpha = 1
})