UIImageView की छवि बदलते समय फीका / भंग


160

दो बनाने के बजाय UIImageViews, केवल imageएक दृश्य को बदलना तर्कसंगत लगता है । अगर मैं ऐसा करता हूं, तो क्या एक झटके / क्रॉस को तत्काल स्विच के बजाय दो छवियों के बीच भंग कर दिया जाता है?


1
@ कुमार-केएल आपके संपादन ने एक महत्वपूर्ण टैग हटा दिया। कृपया ऐसा मत करो।
एरिक आया

1
@KumarKL लेकिन यहाँ "उद्देश्य-सी" है नहीं एक कम प्राथमिकता टैग! इसे केवल "स्विफ्ट" जोड़ने के लिए न निकालें, इसका कोई मतलब नहीं है, यह वास्तव में सीमा पर बर्बरता है ...
एरिक आया

1
@ EricD, ठीक है मैं वही नहीं दोहराऊंगा। आपकी चिंता के लिए धन्यवाद।
कुमार केएल

जवाबों:


45

संपादित करें: नीचे @algal से बेहतर समाधान है ।

ऐसा करने का एक और तरीका पूर्वनिर्धारित CAAimimation बदलाव का उपयोग करना है:

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 से दृश्य परिवर्तन उदाहरण परियोजना देखें: https://developer.apple.com/library/content/samplecode/ViewTransitions/Introduct/Intro.html#//apple_ref/doc/uid/DTSD0000007411


1
उत्तम! मैं इस कोड का हिस्सा SDWebImage की UIImageView (WebCache) श्रेणी में जोड़ता हूं।
ऑटोबोट्स

@OutMan आप नीचे उपयोगकर्ता 577888 द्वारा नई पद्धति का उपयोग करके बेहतर हो सकते हैं।
मिरकुल्स

मैं उस तरह से एक SDWebImages कॉलबैक के बाद अपनी छवि सेट कर रहा हूं, लेकिन किसी कारण से मेरे संग्रह में पहली सेल की छवि दिखाई देती है, शुरू में अंतिम दृश्य सेल से एक है यदि मेरे सभी सेल अपडेट होते हैं। मुझे लगता है कि यह प्रेजेंटेशन लेयर या किसी चीज़ की कैशिंग है?!? इसके बारे में कुछ जानते हैं?
जॉर्ज

संपादन के लिए अपग्रेड करें "नीचे @algal से बेहतर समाधान है।"
रॉब

581

यह नए ब्लॉक-आधारित, UIKit animationविधियों का उपयोग करके बहुत सरल हो सकता है ।

मान लीजिए कि निम्नलिखित कोड व्यू कंट्रोलर में है, और UIImageView आप जिसको क्रॉस-डिसॉल्व करना चाहते हैं, वह संपत्ति के माध्यम से सेल्फव्यू का एक सबव्यू है। self.imageViewइसके बाद आपकी जरूरत है:

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

किया हुआ।

और स्विफ्ट में करने के लिए, यह ऐसा है:

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

स्विफ्ट 3, 4 और 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
अन्य उत्तर सही हैं लेकिन पुराने (और / या अत्यधिक क्रिया) हैं।
स्टीवन क्रेमर

3
यह सुपर दृश्य पर संक्रमण करने के लिए आवश्यक नहीं है। मैं UIImageView को लक्ष्य के रूप में निर्दिष्ट करके यह काम करने में कामयाब रहा।
डेसमंड

7
@ user577888 सिर्फ एक छोटी सी बात। आपको खाली पूर्ण ब्लॉक में शून्य पास करना चाहिए। ब्लॉक फ़ंक्शन पॉइंटर्स नहीं हैं (जैसा कि ^ द्वारा दर्शाया गया है) और ऑब्जेक्टिव-सी ऑब्जेक्ट की तरह काम करते हैं। यदि आप NULL से गुजरते हैं, तो संकलक व्याख्या करेगा कि या तो 0 (शून्य *) 0 है। यदि किन्हीं कारणों से संक्रमण के लिए अंतर्निहित कोड: ... गलती से अपनी वैधता की जांच किए बिना पूर्ण ब्लॉक (जैसे [पूर्ण प्रतिलिपि]) के लिए एक संदेश भेजता है, तो यह एक त्रुटि का कारण होगा। तो आपको खाली रहने के लिए ब्लॉक सेट करते समय हमेशा ऑब्जेक्टिव-सी के एनआईएल का उपयोग करना चाहिए।
श्री टी

3
@ Mr.T NULL और nil मूल्य में समान हैं। दोनों को 0 में परिभाषित किया गया है और न ही कभी बदलने की संभावना है। इस प्रकार, NULL का उपयोग करना सुरक्षित है, कहीं भी या आप nil का उपयोग कर सकते हैं।
अश्विन

1
@ Mr.T मेरा कहना है कि एक के ऊपर एक का उपयोग करने से कभी कोई दुर्घटना नहीं होगी क्योंकि संकलित कोड स्तर पर वे समान हैं, और व्यावहारिक कारणों से, हमेशा रहेगा। कंपाइलर चेतावनियों को दबाना एक अच्छा विचार है, सामान्य तौर पर, लेकिन लोगों को यह बताना कि एनआईएल के बजाय NULL का उपयोग करना एक त्रुटि है, बस गलत है।
ऐश्विन


6

हां, आप जो कहते हैं, वह बिल्कुल सही है और इसे करने का तरीका है। मैंने इस विधि को लिखा और हमेशा अपनी छवि में फीका करने के लिए इसका उपयोग किया। मैं इससे निपटता हूं CALayer। इसके लिए आपको Core एनिमेशन आयात करना होगा।

+ (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;
}

आप एक छवि को फीका करने के लिए विपरीत कर सकते हैं। इसके बाद बाहर निकल जाता है। आप इसे केवल पर्यवेक्षण (जो है UIImageView) से हटा दें । [imageView removeFromSuperview]


मैं UIImageView में एक छवि सेट करने के बाद इस कोड को जोड़ता हूं, ऐसा लगता है कि एनीमेशन शुरू करते समय एक पलक होती है।
ऑटोबॉट्स

4

आप एक उपवर्ग में फीका-इन सुविधा को भी पैकेज कर सकते हैं, ताकि आप इसे सामान्य UIImageView के रूप में उपयोग कर सकें, निम्न उदाहरण में:

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

एक संभावित कार्यान्वयन निम्नानुसार है।

नोट: जिस तरह से आप वास्तव में setImage:फ़ंक्शन में फीका-इन लागू करते हैं, वह बदल सकता है, और इस प्रश्न के अन्य उत्तर में वर्णित अन्य उत्कृष्ट उदाहरणों में से एक हो सकता है - एक अतिरिक्त ऑन-द-फ्लाई बनाना UIImageViewजैसा कि मैं यहां कर रहा हूं। अपनी विशिष्ट स्थिति में अस्वीकार्य उपरि बनें

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];
        }];
    }
}

उपरोक्त कोड कुछ मान्यताओं पर निर्भर करता है (ARC सहित आपकी XCode परियोजना में सक्षम होना), यह केवल अवधारणा के प्रमाण के रूप में है, और स्पष्टता और फ़ोकस के हित में, यह महत्वपूर्ण असंबंधित कोड को छोड़ कर प्रासंगिक रहता है। कृपया इसे आँख बंद करके कॉपी-पेस्ट न करें।


3

मुझे अनिश्चित काल तक दोहराने के लिए संक्रमण की आवश्यकता थी। इसके लिए एक परीक्षण और त्रुटि का एक बहुत लिया, लेकिन मैं अंत में मैं देख रहा था अंतिम परिणाम मिल गया। UITableViewCell में UIImageView में छवि एनीमेशन जोड़ने के लिए ये कोड स्निपेट हैं।

यहाँ प्रासंगिक कोड है:

@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;
}

नमस्ते, अगर आप अपने [self setVarietyImageView: cell.imageView] पर कुछ और जानकारी जोड़ सकते हैं तो मुझे आश्चर्य हो रहा था; विधि के रूप में मैं अंतिम कोशिका को चेतन या सभी को चेतन करने के लिए प्राप्त कर सकता हूं लेकिन वास्तव में तेजी से, धन्यवाद
gav

हाय गाव, "विविधताइमेज व्यू" व्यू कंट्रोलर में एक कमजोर संदर्भ है, ताकि मैं सेल.इमेज व्यू को असाइन कर सकूं और बाद में इसे 'एनिमेटमैजेस' विधि में संदर्भित कर सकूं। @property (गैर-परमाणु, कमजोर) UIImageView * विविधताइमेज व्यू; आप "ट्रांज़िशनविथ व्यू" में छोटी "अवधि" सेट करके छवियों को तेज़ी से घुमा सकते हैं। उम्मीद है कि यह आप पूछ रहे हैं।
क्रिस्टोफर

हाय क्रिस्टोफर जवाब के लिए धन्यवाद, मैं "setVarietyImageView" के बारे में सोच रहा था: "मैं इसके कुछ प्रकार के शून्य विधि को मानता हूं जो पुन: उपयोग के लिए अनुमति देता है क्योंकि मैं केवल अंतिम सेल को एनिमेट करने में सक्षम रहा हूं। फिर से जवाब देने के लिए धन्यवाद,
gav

यह विधि मानक "संपत्ति" घोषणा का उपयोग करके उत्पन्न होती है। उदाहरण के लिए, @property (गैर-परमाणु, कमजोर) UIImageView * विविधताइमेज व्यू। यह एक "कमजोर" संदर्भ है क्योंकि यह एक अन्य स्थानीय चर (तालिका सेल की छवि दृश्य) को संदर्भित करता है। मैं इसके बजाय टेबल सेल के लिए एक संदर्भ बना सकता था और सेल को एक्सेस कर सकता था। आशा है कि ये आपकी मदद करेगा।
क्रिस्टोफर

2

विकल्प के साथ खेलने UIView.transition()और समस्याओं के बाद .transitionCrossDissolve(मैं एक UIImageView के अंदर बदलने वाली चेतन छवियों की कोशिश कर रहा था और बिना एनीमेशन के संक्रमण तुरंत हो गया था) मुझे पता चला है कि आपको बस एक और विकल्प जोड़ने की आवश्यकता है जो आपको दृश्य के अंदर बदलने वाले चेतन गुणों को दे रहा है ( स्विफ्ट 4.2 ):

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

इसके अतिरिक्त: यदि आपकी छवि पर कोई साक्षात्कार है, तो इसे फिर से तैयार किया जाएगा और यह एनीमेशन को रोक सकता है। उदाहरण के लिए, मैंने अपनी छवि दृश्य पर धब्बा के साथ सबव्यू किया था और उस मामले में एनीमेशन काम नहीं करता है। इसलिए मैंने सिर्फ अपना दृष्टिकोण पदानुक्रम बदल दिया है और अपने स्वयं के दृश्य को धुंधला कर दिया है और इसे छवि दृश्य पर रख दिया है।


0

मुझे लगता है कि यह करने का सबसे छोटा तरीका है। एक UIView एनीमेशन बनाएं और इसे अपने चित्र पर देखें।

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

0

highlightedImageसंपत्ति का उपयोग करके इसे थोड़ा और सरल बनाया जा सकता है। यहाँ स्विफ्ट 3 में एक उदाहरण है। पहले सामान्य और हाइलाइट की गई छवि दोनों सेट करें:

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

और जब आप उन एनिमेटेड के बीच बदलना चाहते हैं:

UIView.transition(with: imageView, duration: 0.3, options: .transitionCrossDissolve, animations: { self.imageView.isHighlighted = !self.imageView.isHighlighted}, completion: .none)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.