Как анимировать изменение изображения в UIImageView?


199

У меня есть UIImageViewс изображением. Теперь у меня есть совершенно новое изображение (графический файл), и я хочу показать это в этом UIImageView. Если бы я просто установить

myImageView.image = newImage;

новое изображение видно сразу. Не оживляемый.

Я хочу, чтобы это красиво исчезло в новом образе. Я подумал, может быть, есть лучшее решение, чем просто создать новый UIImageViewповерх этого и смешать с анимацией?


Ответы:


260

Я не уверен, что вы можете анимировать UIViews с эффектом затухания, поскольку кажется, что все поддерживаемые переходы вида определены в UIViewAnimationTransitionперечислении. Эффект затухания может быть достигнут с помощью CoreAnimation. Пример примера для этого подхода:

#import <QuartzCore/QuartzCore.h>
...
imageView.image = [UIImage imageNamed:(i % 2) ? @"3.jpg" : @"4.jpg"];

CATransition *transition = [CATransition animation];
transition.duration = 1.0f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;

[imageView.layer addAnimation:transition forKey:nil];

2
Ваш код работал отлично при переходе от одного изображения к другому. Знаете ли вы, как заставить его работать с автоматической анимацией изображений в UIImageView (свойство animationImages)?
CedricSoubrie

Вы можете попробовать использовать CAKeyFrameAnimation для свойства содержимого слоя, хотя не уверены, будет ли эффект таким же. Или установите делегат анимации и в функции обратного вызова делегата начните анимировать следующее изображение, когда закончится предыдущая анимация.
Владимир

2
Это, безусловно, проще, чем пометить вручную отдельный вид изображения. Спасибо!
Кевлар

Ну что ж ... Если фрейм imageviews изменится, то он останется в том же положении ... это прерыватель сделки!
hfossli

@ Фоссли, ты имеешь в виду, когда кадр меняется во время анимации? Это другой вопрос
Владимир

368
[UIView transitionWithView:textFieldimageView
                  duration:0.2f
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    imageView.image = newImage;
                } completion:nil];

другая возможность


1
просто и открывает целый ряд других эффектов анимации между изображениями.
Итак,

1
Имеет ту же проблему, что @hfossli упомянул относительно смены кадров. Анимация была бы вялой, если макеты меняются во время этого.
Гева

1
Это лучшее решение, потому что его можно комбинировать с другими анимациями.
Келин

161

По словам Майкла Скотта, пусть это будет просто глупо. Вот простой способ сделать это в Swift 3 и Swift 4 :

UIView.transition(with: imageView,
                  duration: 0.75,
                  options: .transitionCrossDissolve,
                  animations: { self.imageView.image = toImage },
                  completion: nil)

3
Работает как шарм. Спасибо!
Роберто Альенде

1
Уау здорово! Не знал об этом, черт возьми, так долго :)
Сабиланд

1
Это изменится на 1 изображение. Что делать, если у меня есть массив изображений и я хочу показать их по одному с анимацией перехода?
Аммар Муджиб

1
Вы можете использовать блок завершения для перехода к следующему.
Зия

41

Вот один пример в Swift , который сначала скрестит новое изображение, а затем добавит оживленную анимацию:

var selected: Bool {
  willSet(selected) {
    let expandTransform:CGAffineTransform = CGAffineTransformMakeScale(1.15, 1.15);
    if (!self.selected && selected) {
      UIView.transitionWithView(self.imageView,
        duration:0.1,
        options: UIViewAnimationOptions.TransitionCrossDissolve,
        animations: {
          self.imageView.image = SNStockCellSelectionAccessoryViewImage(selected)
          self.imageView.transform = expandTransform
        },
        completion: {(finished: Bool) in
          UIView.animateWithDuration(0.4,
            delay:0.0,
            usingSpringWithDamping:0.40,
            initialSpringVelocity:0.2,
            options:UIViewAnimationOptions.CurveEaseOut,
            animations: {
              self.imageView.transform = CGAffineTransformInvert(expandTransform)
            }, completion:nil)
      })
    }
  }
}

var imageView:UIImageView

Если imageViewправильно добавлен к просмотру как подвид, переключаясь между selected = falseк selected = trueдолжен поменять изображение с надувной анимацией. SNStockCellSelectionAccessoryViewImageпросто возвращает другое изображение в зависимости от текущего состояния выбора, см. ниже:

private let SNStockCellSelectionAccessoryViewPlusIconSelected:UIImage = UIImage(named:"PlusIconSelected")!
private let SNStockCellSelectionAccessoryViewPlusIcon:UIImage = UIImage(named:"PlusIcon")!

private func SNStockCellSelectionAccessoryViewImage(selected:Bool) -> UIImage {
  return selected ? SNStockCellSelectionAccessoryViewPlusIconSelected : SNStockCellSelectionAccessoryViewPlusIcon
}

Пример GIF ниже немного замедлен, фактическая анимация происходит быстрее:

                                       UIImageView отказов анимация Gif


16

Код:

var fadeAnim:CABasicAnimation = CABasicAnimation(keyPath: "contents");

fadeAnim.fromValue = firstImage;
fadeAnim.toValue   = secondImage;
fadeAnim.duration  = 0.8;         //smoothest value

imageView.layer.addAnimation(fadeAnim, forKey: "contents");

imageView.image = secondImage;

Пример:

Пример UIImageView из кода

Веселое, более подробное решение : ( переключение на кране )

    let fadeAnim:CABasicAnimation = CABasicAnimation(keyPath: "contents");

    switch imageView.image {
        case firstImage?:
            fadeAnim.fromValue = firstImage;
            fadeAnim.toValue   = secondImage;
            imageView.image    = secondImage;
        default:
            fadeAnim.fromValue = secondImage;
            fadeAnim.toValue   = firstImage;
            imageView.image    = firstImage;
    }

    fadeAnim.duration = 0.8;

    imageView.layer.addAnimation(fadeAnim, forKey: "contents");


8

С Swift 3

extension UIImageView{   
 var imageWithFade:UIImage?{
        get{
            return self.image
        }
        set{
            UIView.transition(with: self,
                              duration: 0.5, options: .transitionCrossDissolve, animations: {
                                self.image = newValue
            }, completion: nil)
        }
    }
}

Использование:

myImageView.imageWithFade = myImage

6

Почему бы не попробовать это.

NSArray *animationFrames = [NSArray arrayWithObjects:
  [UIImage imageWithName:@"image1.png"],
  [UIImage imageWithName:@"image2.png"], 
  nil];

UIImageView *animatedImageView = [[UIImageView alloc] init];
animatedImageView.animationImages = animationsFrame;
[animatedImageView setAnimationRepeatCount:1];
[animatedImageView startAnimating];

Быстрая версия:

let animationsFrames = [UIImage(named: "image1.png"), UIImage(named: "image2.png")]
let animatedImageView = UIImageView()
animatedImageView.animationImages = animationsFrames
animatedImageView.animationRepeatCount = 1
animatedImageView.startAnimating()

Это заставляет UIImageView повторять переключение навсегда ... однако автор просто просил об изменении :(
J-Dizzle

setAnimationRepeatCount
Уильям Ху

SetAnimationRepeatCount ничего не меняет. Это никогда не останавливается
Юсель Байрам

5
CABasicAnimation* fadeAnim = [CABasicAnimation animationWithKeyPath:@"contents"];
fadeAnim.fromValue = (__bridge id)imageView.image.CGImage;
fadeAnim.toValue = (__bridge id)[UIImage imageNamed:@"newImage.png"].CGImage;
fadeAnim.duration = 2.0;
[imageView.layer addAnimation:fadeAnim forKey:@"contents"];
imageView.layer.contents = (__bridge id)[UIImage imageNamed:@"newImage.png"].CGImage;

3

Здесь есть несколько разных подходов: UIAnimations, насколько я помню, звучит как ваша задача.

Редактировать: мне лень :)

В посте я имел в виду этот метод:

[newView setFrame:CGRectMake( 0.0f, 480.0f, 320.0f, 480.0f)]; //notice this is OFF screen!
[UIView beginAnimations:@"animateTableView" context:nil];
[UIView setAnimationDuration:0.4];
[newView setFrame:CGRectMake( 0.0f, 0.0f, 320.0f, 480.0f)]; //notice this is ON screen!
[UIView commitAnimations];

Но вместо анимации фрейма вы анимируете альфа:

[newView setAlpha:0.0]; // set it to zero so it is all gone.
[UIView beginAnimations:@"animateTableView" context:nil];
[UIView setAnimationDuration:0.4];
[newView setAlpha:0.5]; //this will change the newView alpha from its previous zero value to 0.5f
[UIView commitAnimations];

2

Начиная с iOS 5 этот намного проще:

[newView setAlpha:0.0];
[UIView animateWithDuration:0.4 animations:^{
    [newView setAlpha:0.5];
}];

4
Это не помогает исходной проблеме, которая заключается в том, что у вас уже есть изображение, и вы хотите постепенно перейти к новому изображению ...
Кендалл Хельмштеттер Гелнер

4
правильно .. этот ответ не решает вопрос. Вопрос заключался не в том, как исчезать при просмотре изображений, а в том, чтобы перейти от старого изображения к новому. Анимационные блоки были введены в iOS 4.
Бастиан

2

Swift 4 Это просто потрясающе

  self.imgViewPreview.transform = CGAffineTransform(scaleX: 0, y: 0)
          UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0, options: .curveEaseOut, animations: {
              self.imgViewPreview.image = newImage
              self.imgViewPreview.transform = .identity
          }, completion: nil)

1

Ответ Владимира идеален, но любой, как я, ищет быстрое решение

Это решение работает для быстрой версии 4.2

var i = 0
    func animation(){
        let name = (i % 2 == 0) ? "1.png" : "2.png"
        myImageView.image = UIImage.init(named: name)
        let transition: CATransition = CATransition.init()
        transition.duration = 1.0
        transition.timingFunction = CAMediaTimingFunction.init(name: .easeInEaseOut)
        transition.type = .fade
        myImageView.layer.add(transition, forKey: nil)
        i += 1
    }

Вы можете вызвать этот метод из любого места. Это изменит изображение на следующее (изображение) с анимацией.

Для Swift версии 4.0 Используйте решение ниже

var i = 0
    func animationVersion4(){
        let name = (i % 2 == 0) ? "1.png" : "2.png"
        uiImage.image = UIImage.init(named: name)
        let transition: CATransition = CATransition.init()
        transition.duration = 1.0
        transition.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut)
        transition.type = kCATransitionFade
        uiImage.layer.add(transition, forKey: nil)
        i += 1
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.