2014-07-10 10 views
12

किसी दृश्य के लिए UIView एनीमेशन में, आप के विकल्प पैरामीटर में UIViewAnimationOptionLayoutSubviews सहित सबव्यू को एनिमेट कर सकते हैं। हालांकि, मुझे sublayers डालने पर एनिमेट करने का कोई तरीका नहीं मिल रहा है जब वे कुछ दृश्य की बैकिंग परत नहीं हैं; वे दृश्य की नई सीमाओं से मेल खाने के लिए बस जगह पर कूद जाएंगे। चूंकि मैं परतों के साथ काम कर रहा हूं और विचार नहीं देख रहा हूं, ऐसा लगता है कि मुझे UIView एनीमेशन के बजाय कोर एनीमेशन का उपयोग करना है, लेकिन मुझे नहीं पता कि कैसे (और कब) ऐसा करने के लिए कि परत एनीमेशन दृश्य से मेल खाता है एनीमेशन।UIView एनीमेशन के दौरान UIView की परत के उपन्यासों को आप कैसे एनिमेट करते हैं?

यह मेरा मूल प्रश्न है। यदि आप उस ठोस चीज को जानना चाहते हैं जो मैं पूरा करने की कोशिश कर रहा हूं तो और पढ़ें।

मैंने दृश्य की परत में एक कैशपलेयर जोड़कर एक बिंदीदार सीमा के साथ एक दृश्य बनाया है (यह स्टैक ओवरफ्लो प्रश्न देखें: Dashed line border around UIView)। मैं layoutSubviews में दृश्य की सीमाओं से मेल खाने के लिए CAShapeLayer के पथ को समायोजित करता हूं।

यह काम करता है, लेकिन एक कॉस्मेटिक मुद्दा है: जब दृश्य की सीमाएं UIView एनीमेशन (जैसे घूर्णन के दौरान) में एनिमेटेड होती हैं, तो बिंदीदार सीमा दृश्य के रूप में आसानी से एनिमेट करने के बजाय दृश्य की नई सीमाओं पर कूद जाती है इसकी सीमाओं को एनिमेट करता है। यही है, बिंदीदार सीमा के दाएं और निचले भाग क्रमशः दृश्य के दाएं और निचले हिस्से में गले लगाए जाते हैं क्योंकि दृश्य एनिमेट करता है। मैं कैशपलेयर से बिंदीदार सीमा को दृश्य के साथ एनिमेट करने के लिए कैसे प्राप्त कर सकता हूं क्योंकि यह इसकी सीमाओं को एनिमेट करता है?

क्या मैं अब तक कर रहा हूँ CAShapeLayer करने के लिए एक CABasicAnimation संलग्न है:

- (void)layoutSubviews 
{ 
    [super layoutSubviews]; 

    self.borderLayer.path = [UIBezierPath bezierPathWithRect:self.bounds].CGPath; 
    self.borderLayer.frame = self.bounds; 

    CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"]; 
    [self.borderLayer addAnimation:pathAnimation forKey:nil]; 
} 

यह चेतन करने के लिए बिंदीदार सीमा का कारण है, लेकिन यह सही समय समारोह और एनीमेशन अवधि मैच के लिए नहीं है दृश्य एनीमेशन। इसके अलावा, कभी-कभी, हम नहीं चाहते हैं कि बिंदीदार सीमा को एनिमेट करना पड़े, जब दृश्य पहले लेआउट करता है, तो सीमा को नए पुराने पथ से कुछ पुराने पथ से एनिमेट नहीं करना चाहिए; यह सिर्फ प्रकट होना चाहिए।

उत्तर

19

आपको पहले से ही जवाब मिल गया होगा, लेकिन मुझे हाल ही में इसी तरह की समस्याओं का सामना करना पड़ा, क्योंकि इसे हल करने के बाद, मैं जवाब पोस्ट करूंगा।

- layoutSubViews विधि में, आप - animationForKey: विधि के साथ समर्थन परत की CAAnimation के रूप में वर्तमान UIView एनीमेशन प्राप्त कर सकते हैं। इस का प्रयोग, आप लागू कर सकते हैं - layoutSubviews की तरह:

- (void)layoutSubviews { 
    [super layoutSubviews]; 

    // get current animation for bounds 
    CAAnimation *anim = [self.layer animationForKey:@"bounds"]; 

    [CATransaction begin]; 
    if(anim) { 
     // animating, apply same duration and timing function. 
     [CATransaction setAnimationDuration:anim.duration]; 
     [CATransaction setAnimationTimingFunction:anim.timingFunction]; 

     CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"]; 
     [self.borderLayer addAnimation:pathAnimation forKey:@"path"]; 
    } 
    else { 
     // not animating, we should disable implicit animations. 
     [CATransaction disableActions]; 
    } 

    self.borderLayer.path = [UIBezierPath bezierPathWithRect:self.bounds].CGPath; 
    self.borderLayer.frame = self.bounds; 
    [CATransaction commit]; 
} 
+4

मैं animationForKey पाने के लिए "स्थिति" संपत्ति का इस्तेमाल किया था, लेकिन उस के अलावा यह मेरे लिए महान काम किया! – Eric

+2

धन्यवाद, लेकिन मुझे जिक्र करना चाहिए कि यह एनीमेशन विधि के साथ काम नहीं करता है [UIView एनिमेटथिथेशन: एसप्रिंगविथडैम्पिंग का उपयोग: प्रारंभिक प्रसंस्करण वेग: विकल्प: एनिमेशन: समापन:] –

+1

@Eric आप 'bounds.size' का भी उपयोग कर सकते हैं। एक त्वरित ब्रेकपॉइंट और एनीमेशन की जांच करना मुझे बताता है कि 3 एनीमेशन चल रहे हैं '[स्थिति, बाउंड्स साइज, बाउंड्सओरिगिन] ' –

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