2012-02-21 17 views
13

में एनिमेटिंग नहीं कर रहा है मुझे लगता है कि मैं कुछ प्राथमिक दिख रहा हूं, लेकिन इंटरनेट पर गलत होने के बजाय इसे खोजने का बेहतर तरीका क्या है?CAGradientLayer गुण UIView एनीमेशन ब्लॉक

मेरे पास काफी मूल यूआई है। मेरे UIViewController के लिए दृश्य एक उपclass है जिसका +layerClassCAGradientLayer है। उपयोगकर्ता के कार्यों के आधार पर, मुझे कुछ UI तत्वों को स्थानांतरित करने और पृष्ठभूमि के ढाल के मानों को बदलने की आवश्यकता है। कोड इस तरह दिखता है:

[UIView animateWithDuration:0.3 animations:^{ 
    self.subview1.frame = CGRectMake(...); 
    self.subview2.frame = CGRectMake(...); 
    self.subview2.alpha = 0; 

    NSArray* newColors = [NSArray arrayWithObjects: 
         (id)firstColor.CGColor, 
         (id)secondColor.CGColor, 
         nil]; 
    [(CAGradientLayer *)self.layer setColors:newColors]; 
}]; 

मुद्दा यह है कि परिवर्तन मैं subviews को यह ब्लॉक में बनाना ठीक (सामान ले जाता है और fades) चेतन है, लेकिन ढाल के रंग को नहीं बदलता है। यह बस स्वैप।

अब, the documentation does say कि एनीमेशन ब्लॉक के भीतर कोर एनीमेशन कोड ब्लॉक की गुणों (अवधि, आसान, इत्यादि) का वारिस नहीं करेगा। लेकिन क्या यह मामला है कि यह एनीमेशन लेनदेन को बिल्कुल परिभाषित नहीं करता है? (किए गए दस्तावेज़ों की निहितार्थ यह है कि आप एक डिफ़ॉल्ट एनीमेशन मिल जाएगा हो सकता है, जहां मैं कोई भी मिल रहा है।)

मैं स्पष्ट CAAnimation उपयोग करने के लिए यह काम करने के लिए है? (और यदि हां, तो क्यों?)

उत्तर

13

यहां दो चीजें चल रही हैं। पहला (जैसा कि ट्रैविस सही ढंग से इंगित करता है, और दस्तावेज कहता है) यह है कि UIKit एनिमेशन CALayer संपत्ति परिवर्तनों पर लागू निहित एनीमेशन पर किसी भी तरह का प्रभाव नहीं लग रहा है। मुझे लगता है कि यह अजीब है (UIKit कोर एनीमेशन का उपयोग कर रहे हैं), लेकिन यह वही है।

यहाँ है कि समस्या के लिए एक (? संभवतः बहुत गूंगा) वैकल्पिक हल है:

NSTimeInterval duration = 2.0; // slow things down for ease of debugging 
    [UIView animateWithDuration:duration animations:^{ 
    [CATransaction begin]; 
    [CATransaction setAnimationDuration:duration]; 

    // ... do stuff to things here ... 

    [CATransaction commit]; 
    }]; 

अन्य प्रमुख है कि इस ढाल परत मेरे विचार की परत है। इसका मतलब है कि मेरा विचार परत का प्रतिनिधि है (जहां, यदि ढाल परत केवल एक उपनगर था, तो उसके पास प्रतिनिधि नहीं होगा)। घटना के लिए UIView-actionForLayer:forKey:NSNull का कार्यान्वयन करता है। (शायद हर घटना जो UIView एनिमेशन की एक विशिष्ट सूची पर नहीं है।)

मेरे विचार के लिए निम्न कोड रंग बदलने का कारण होगा जोड़ा जा रहा है के रूप में उम्मीद एनिमेटेड करने के लिए किया जा:

- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event 
{ 
    id<CAAction> action = [super actionForLayer:layer forKey:event]; 
    if([@"colors" isEqualToString:event] 
     && (nil == action || (id)[NSNull null] == action)) { 
    action = [CABasicAnimation animationWithKeyPath:event]; 
    } 
    return action; 
} 
+0

शानदार खोज! इस पर कभी अनुमान लगाया नहीं होगा। –

1

आपको स्पष्ट CAAnimimations का उपयोग करना होगा, क्योंकि आप एक कैलियर का मान बदल रहे हैं। UIViewAnimations उनके CALayer के गुणों पर सीधे UIView संपत्तियों पर काम करते हैं, लेकिन नहीं ...

ताकि आप अपने fromValue और toValue गुण का उपयोग कर सकते वास्तव में, यदि आप एक CABasicAnimation उपयोग करना चाहिए।

निम्नलिखित कोड आप के लिए काम करना चाहिए:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    [UIView animateWithDuration:2.0f 
          delay:0.0f 
         options:UIViewAnimationCurveEaseInOut 
        animations:^{ 
         CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"colors"]; 
         animation.duration = 2.0f; 
         animation.delegate = self; 
         animation.fromValue = ((CAGradientLayer *)self.layer).colors; 
         animation.toValue = [NSArray arrayWithObjects:(id)[UIColor blackColor].CGColor,(id)[UIColor whiteColor].CGColor,nil]; 
         [self.layer addAnimation:animation forKey:@"animateColors"]; 
        } 
        completion:nil]; 
} 

-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 
    NSString *keyPath = ((CAPropertyAnimation *)anim).keyPath; 
    if ([keyPath isEqualToString:@"colors"]) { 
     ((CAGradientLayer *)self.layer).colors = ((CABasicAnimation *)anim).toValue; 
    } 
} 

कि में CAAnimations साथ एक चाल है कि आप स्पष्ट रूप के बाद आप एनीमेशन को पूरा संपत्ति के मूल्य सेट करना होगा।

आप प्रतिनिधि को सेट करके ऐसा करते हैं, इस मामले में मैंने इसे उस ऑब्जेक्ट पर सेट किया है जो एनीमेशन को कॉल करता है, और उसके बाद animationDidStop:finished: विधि को ओवरराइड करता है ताकि CAGradientLayer के रंगों को उनके अंतिम मान में सेट किया जा सके।

एनीमेशन के गुणों तक पहुंचने के लिए आपको animationDidStop: विधि में थोड़ा कास्टिंग करना होगा।

+0

बात है, CALayer गुण निहित एनिमेशन की है। ऐसा लगता है कि UIView एनीमेशन द्वारा परिभाषित एनीमेशन गुणों को कैलियर परिवर्तनों पर लागू नहीं किया गया है, लेकिन यह स्पष्ट नहीं करता है कि मैं रंग परिवर्तन के * किसी * एनीमेशन को क्यों नहीं देख रहा हूं। –

+0

दोनों UIView और CALayer के पास निहित एनिमेशन हैं। जब आप UIViewAnimation को ट्रिगर करते हैं, और आप अपने कैलियर पर एनीमेशन ट्रिगर करना चाहते हैं तो आपको इसे एक ही समय में स्पष्ट रूप से करना होगा। UIView के एनिमेशन में CABasicAnimation क्या करता है:^{} ब्लॉक ... –

+0

लेकिन कुंजी यह है कि निहित एनीमेशन नहीं हो रहा है क्योंकि प्रश्न में परत * व्यू * परत है। UIView एनीमेशन ब्लॉक के अंदर परिवर्तन किया गया है या नहीं, यह एक पूरी तरह से अलग चिंता है। (निहित एनिमेशन का पूरा बिंदु यह है कि उन्हें स्पष्ट एनीमेशन ब्लॉक की आवश्यकता नहीं है।) –

संबंधित मुद्दे