UIImageView görüntüsünü değiştirirken solma / çözme


160

İki görünüm oluşturmak yerine , tek bir görünümün UIImageViewsdeğiştirilmesi mantıklı görünmektedir image. Bunu yaparsam, bir anlık anahtar yerine iki görüntü arasında solma / çapraz çözünme var mı?


1
@ kumar-kl Düzenlemeniz önemli bir etiketi kaldırdı. Lütfen yapma.
Eric Aya

1
@KumarKL Ama burada "nesnel-c" dir değil düşük bir öncelik etiketi! Sadece "hızlı" eklemek için kaldırmayın, bu hiç mantıklı değil, aslında sınırda vandalizm ...
Eric Aya

1
@EricD, Tamam aynı şeyi tekrarlamayacağım. İlginiz için teşekkürler.
Kumar KL

Yanıtlar:


45

Düzenleme: @ @galgal'den daha iyi bir çözüm var .

Bunu yapmanın başka bir yolu, önceden tanımlanmış CAAnimation geçişlerini kullanmaktır:

CATransition *transition = [CATransition animation];
transition.duration = 0.25;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
transition.delegate = self;
[self.view.layer addAnimation:transition forKey:nil];
view1.hidden = YES;
view2.hidden = NO;

Apple'dan Geçişleri Görüntüle örnek projesine bakın: https://developer.apple.com/library/content/samplecode/ViewTransitions/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007411


1
Mükemmel! Bu kodun bir kısmını SDWebImage'ın UIImageView (WebCache) kategorisine ekliyorum.
Autobotlar

@OutMan user577888 tarafından aşağıdaki yeni yöntemi kullanarak daha iyi olabilirsiniz.
Mirkules

Ben de bu şekilde bir SDWebImages geri arama sonra benim görüntüyü ayarlıyorum, ama bazı nedenlerden dolayı benim CollectionViewCell ilk hücrenin görüntü, tüm hücrelerim güncellenirse başlangıçta son görünür hücreden biridir. Sanırım sunumu önbelleğe almak bir tür önbellek falan mı?!? Ne olabileceğine dair bir fikrin var mı?
Georg

"Aşağıdaki @algal'dan daha iyi bir çözüm var" düzenlemesine oy verin.
Rob

581

Yeni blok tabanlı UIKit animationyöntemleri kullanmak çok daha basit olabilir .

Aşağıdaki kod görünümü denetleyicisi olduğunu, ve çapraz erimesi istediğiniz UIImageView özelliği aracılığıyla self.view adreslenebilir bir Subview olduğunu varsayalım self.imageViewolan tüm gerekmez Ardından:

    UIImage * toImage = [UIImage imageNamed:@"myname.png"];
    [UIView transitionWithView:self.imageView
                      duration:5.0f
                       options:UIViewAnimationOptionTransitionCrossDissolve
                    animations:^{
                      self.imageView.image = toImage;
                    } completion:nil]

Bitti.

Ve Swift'te yapmak için, şöyle:

    let toImage = UIImage(named:"myname.png")
    UIView.transitionWithView(self.imageView,
                              duration:5,
                              options: UIViewAnimationOptions.TransitionCrossDissolve,
                              animations: { self.imageView.image = toImage },
                              completion: nil)

Hızlı 3, 4 ve 5

     let toImage = UIImage(named:"myname.png")
     UIView.transition(with: self.imageView,
                       duration: 0.3,
                       options: .transitionCrossDissolve,
                       animations: {
                           self.imageView.image = toImage
                       },
                       completion: nil)

3
Diğer cevaplar doğru ama modası geçmiş (ve / veya aşırı ayrıntılı).
Steven Kramer

3
Süper görünümde geçiş yapmak gerekli değildir. UIImageView kendisini hedef olarak belirterek bu işi başardı.
Desmond

7
@ user577888 sadece küçük bir şey. Boş tamamlama bloğuna sıfır geçmelisiniz. Bloklar (^ ile belirtildiği gibi) işlev işaretçileri değildir ve bir obj-c nesnesi gibi çalışırlar. NULL değerini iletirseniz, derleyici bunu 0 veya (void *) 0 olarak yorumlar. Geçiş kodu için temel kod herhangi bir nedenle geçerliliğini kontrol etmeden yanlışlıkla tamamlama bloğuna (örneğin [tamamlama kopyası]) bir mesaj gönderirse, bu bir hataya yol açar. Bu yüzden bir bloğu boş olarak ayarlarken objektif-c'nin sıfırını kullanmalısınız.
Bay T

3
@ Mr.T NULL ve nil değerleri aynı. Her ikisi de 0 olarak tanımlanmıştır ve her ikisinin de değişme olasılığı yoktur. Böylece, nULL kullanacağınız veya kullanabileceğiniz her yerde NULL kullanmak güvenlidir.
ashevin

1
@ Mr.T Demek istediğim, birini diğerinin üzerinde kullanmak asla bir çökmeye neden olmayacak çünkü derlenmiş kod düzeyinde aynılar ve pratik nedenlerle, her zaman olacak. Derleyici uyarılarını bastırmak genel olarak iyi bir fikirdir, ancak insanlara nil yerine NULL kullanmanın bir hata olduğunu söylemek yanlıştır.
ashevin


6

Evet söyledikleriniz kesinlikle doğrudur ve bunu yapmanın yolu budur. Bu yöntemi yazdım ve her zaman görüntümde solmaya kullanın. Bununla ilgileniyorum CALayer. Bunun için Temel Animasyonu içe aktarmanız gerekir.

+ (void)fadeInLayer:(CALayer *)l
{
    CABasicAnimation *fadeInAnimate   = [CABasicAnimation animationWithKeyPath:@"opacity"];
    fadeInAnimate.duration            = 0.5;
    fadeInAnimate.repeatCount         = 1;
    fadeInAnimate.autoreverses        = NO;
    fadeInAnimate.fromValue           = [NSNumber numberWithFloat:0.0];
    fadeInAnimate.toValue             = [NSNumber numberWithFloat:1.0];
    fadeInAnimate.removedOnCompletion = YES;
    [l addAnimation:fadeInAnimate forKey:@"animateOpacity"];
    return;
}

Bir görüntüyü yavaşlatmak için tam tersini yapabilirsiniz. Sönükleştikten sonra. Sadece denetimden kaldırın (ki UIImageView). [imageView removeFromSuperview].


UIImageView içine bir görüntü ayarladıktan sonra bu kodu eklemek, animasyon başlarken bir göz kırpma var gibi görünüyor.
Autobotlar

4

Ayrıca, soluklaştırma özelliğini bir alt sınıfta paketleyebilir, böylece aşağıdaki örnekte olduğu gibi ortak bir UIImageView olarak kullanabilirsiniz:

IMMFadeImageView *fiv=[[IMMFadeImageView alloc] initWithFrame:CGRectMake(10, 10, 50, 50)];
[self.view addSubview:fiv];
fiv.image=[UIImage imageNamed:@"initialImage.png"];
fiv.image=[UIImage imageNamed:@"fadeinImage.png"];  // fades in

Bunu olası bir uygulama izler.

Not: setImage:işlevde solmaya karşı uygulama şekliniz değişebilir ve bu sorunun diğer yanıtlarında açıklanan diğer mükemmel örneklerden biri olabilir - UIImageViewburada yaptığım gibi anında bir ek oluşturma özel durumunuzda kabul edilemez bir ek yük olmak .

IMMFadeImageView.h :

#import <UIKit/UIKit.h>

@interface IMMFadeImageView : UIImageView
@property (nonatomic,assign) float fadeDuration;
@end

IMMFadeImageView.m :

#import "IMMFadeImageView.h"

@implementation IMMFadeImageView
@synthesize fadeDuration;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.fadeDuration=1;
    }
    return self;
}
-(void)setImage:(UIImage *)newImage{

    if(!self.image||self.fadeDuration<=0){
        super.image=newImage;
    } else {
        UIImageView *iv=[[UIImageView alloc] initWithFrame:self.bounds];
        iv.contentMode=self.contentMode;
        iv.image=super.image;
        iv.alpha=1;
        [self addSubview:iv];
        super.image=newImage;
        [UIView animateWithDuration:self.fadeDuration delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
            iv.alpha=0;
        } completion:^(BOOL finished) {
            [iv removeFromSuperview];
        }];
    }
}

Yukarıdaki kod (XCode projenizde ARC'nin etkinleştirilmesi de dahil olmak üzere) birkaç varsayımlara dayanır, sadece kavramın bir kanıtı olarak tasarlanmıştır ve netlik ve odaklanma açısından, önemli ilişkisiz kodu atlayarak ilgili kalır. Lütfen sadece körü körüne kopyalayıp yapıştırmayın.


3

Süresiz olarak tekrarlamak için geçişe ihtiyacım vardı. Bu bir sürü deneme yanılma aldı ama sonunda aradığım sonucu aldım. Bunlar, bir UITableViewCell'de bir UIImageView'e görüntü animasyonu eklemek için kod parçacıklarıdır.

İlgili kod:

@interface SomeViewController ()
@property(nonatomic, strong) NSMutableArray *imagesArray;
@property(nonatomic, assign) NSInteger varietyImageAnimationIndex;
@property(nonatomic, assign) BOOL varietyImagesAnimated;
@end

@implementation SomeViewController
@synthesize imagesArray;
@synthesize varietyImageAnimationIndex;
@synthesize varietyImagesAnimated;
...

// NOTE: Initialize the array of images in perhaps viewDidLoad method.

-(void)animateImages
{
    varietyImageAnimationIndex++;

    [UIView transitionWithView:varietyImageView
                      duration:2.0f
                       options:UIViewAnimationOptionTransitionCrossDissolve
                    animations:^{
                        varietyImageView.image = [imagesArray objectAtIndex:varietyImageAnimationIndex % [imagesArray count]];
                    } completion:^(BOOL finished) {
                        [self animateImages];
                    }];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   ...
        [cell.imageView setImage:[imagesArray objectAtIndex:0]];


        [self setVarietyImageView:cell.imageView];

        if (! varietyImagesAnimated)
        {
            varietyImagesAnimated = YES;
            [self animateImages];
        }

    ...
    return cell;
}

Merhaba ben senin [self setVarietyImageView: cell.imageView] hakkında biraz daha bilgi eklemek olabilir merak ediyordum; Ben hareket veya son derece canlandırmak için son hücrenin alabilirsiniz gibi yöntem ama gerçekten hızlı, Teşekkürler
gav

Merhaba Gav, "varietyImageView" görünüm denetleyicisinde zayıf bir referanstır, böylece cell.imageView'a atayabilir ve daha sonra 'animateImages' yönteminde başvurabilirim. @property (anatomik olmayan, zayıf) UIImageView * varietyImageView; "TransitionWithView" içinde daha kısa bir "süre" ayarlayarak görüntülerin daha hızlı dönmesini sağlayabilirsiniz. Umarım istediğin budur.
Christopher

Merhaba Christopher cevap için teşekkür ederim, "setVarietyImageView" hakkında merak ediyordum: Ben sadece son hücreyi canlandırmak mümkün olduğu gibi yeniden kullanımına izin veren bir tür geçersiz yöntem varsayalım. Tekrar yanıtladığınız için teşekkür ederiz, en iyi Gav
gav

Bu yöntem standart "özellik" bildirimi kullanılarak oluşturulur. Örneğin, @property (anatomik olmayan, zayıf) UIImageView * varietyImageView. Başka bir yerel değişkene (tablo hücresinin imageView) atıfta bulunduğundan "zayıf" bir referanstır. Bunun yerine tablo hücresine bir başvuru yaptı ve yöntem animateImages cell.imageView erişmiş olabilir. Umarım bu yardımcı olur.
Christopher

2

Etrafta oynadıktan UIView.transition()ve .transitionCrossDissolveseçeneklerle ilgili sorunlar aldıktan sonra (bir UIImageView içinde değişen görüntüleri canlandırmaya çalışıyordum ve animasyon olmadan anında gerçekleşti) Sadece görünümün içinde değişen özellikleri canlandırmanıza izin veren bir seçenek daha eklemeniz gerektiğini öğrendim ( Swift 4.2 ) ile ilişkili olan kısmını dışarı aktarmak suretiyle yedek oluşturmanız gerekir :

UIView.transition(with: self.imageView,
                   duration: 1,
                   options: [.allowAnimatedContent, .transitionCrossDissolve],
                   animations: { self.imageView.image = newImage },
                   completion: nil)

Buna ek olarak: imageView üzerinde alt görünümleriniz varsa, yeniden çizilecek ve animasyonu engelleyebilir. Örneğin, benim imageView üzerinde bulanıklık ile alt görünüm vardı ve bu durumda animasyon çalışmıyor. Bu yüzden görünüm hiyerarşimi değiştirdim ve bulanıklığı kendi görünümüne taşıdım ve imageView üzerine koydum.


0

Bence bunu yapmanın en kısa yolu. Bir UIView animasyonu oluşturun ve bunu imageView üzerinde gerçekleştirin.

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[myImageView setAlpha:0.0];
[UIView commitAnimations];

0

highlightedImageÖzelliği kullanarak bu biraz daha basit hale getirilebilir. Swift 3'te bir örnek: Önce hem normal hem de vurgulanan görüntüyü ayarlayın:

let imageView = UIImageView(image: UIImage(named: "image"), highlightedImage: UIImage(named: "highlightedImage"))

Animasyonlu olanlar arasında geçiş yapmak istediğinizde:

UIView.transition(with: imageView, duration: 0.3, options: .transitionCrossDissolve, animations: { self.imageView.isHighlighted = !self.imageView.isHighlighted}, completion: .none)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.