2012-02-29 10 views
14

Uygulamalarımdan biri için otomatik uyum dostu bölünmüş bir görünüm sınıfı oluşturuyorum. Çeşitli özellikleri arasında, bölmeleri daraltması ve NSSplitView uygulamasının görebildiğiniz gibi çöküşlerini canlandırabilmesidir. I kısıtlamaları kullanıyorum yanaNSLayoutConstraint.constant animasyonu görmezden geliyor

ben ayarlama sonra bölmedeki gerekli genişlik = (mevcut genişlik) kısıtlamasını yerleştirilmesi ve bu elde ediyorum hareketli bir şekilde kısıtlama sabiti 0:

- (NSLayoutConstraint*)newHiddenConstraintAnimated:(BOOL)animated { 
    NSLayoutConstraint * constraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:NSWidth(self.view.frame)]; 
    constraint.priority = NSLayoutPriorityRequired; 

    CABasicAnimation * anim = [CABasicAnimation animation]; 
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 
    anim.duration = 0.2; 
    constraint.animations = [NSDictionary dictionaryWithObject:anim forKey:@"constant"]; 

    [self.view addConstraint:constraint]; 

    [(animated ? constraint.animator : constraint) setConstant:0.0]; 

    return constraint; 
} 

Bu güzel çalışıyor. Ne yazık ki, daha sonra bölmeyi genişletmek o kadar iyi değildir. Bazı zamanlama kodunu eklerseniz

- (void)removeHiddenConstraintAnimated:(BOOL)animated { 
    if(!animated) { 
     [self.view removeConstraint:self.hiddenConstraint]; 
    } 
    else { 
     NSLayoutConstraint * constraint = self.hiddenConstraint; 
     NSView * theView = self.view; 

     [NSAnimationContext beginGrouping]; 

     [constraint.animator setConstant:self.width]; 

     [NSAnimationContext currentContext].completionHandler = ^{ 
      [theView removeConstraint:constraint]; 
     }; 

     [NSAnimationContext endGrouping]; 
    } 

    self.hiddenConstraint = nil; 
} 

, bunu canlandırmak zamanı bulamadan kısıtlamayı kaldırarak, tamamlama işleyicisi neredeyse anında patlar olduğunu görebilirsiniz. NSAnimationContext'de bir sürenin ayarlanması bir etkisi yoktur.

Burada ne yapıyorum diye bir fikrim var mı?

+0

Bu bölünmüş görünüm sınıfını hiç bitirdiniz mi? Açık kaynak olma ihtimali var mı? –

+0

Şu an plan yapmıyorum. Bu uygulama için oldukça uzmanlaşmış ve inanıyorum ki [PURRDACTED] 'de NSSplitView' autolayout ile daha iyi çalışacak şekilde yeniden tasarlandı. –

+0

Oh, gotcha. [Yeniden düzenlenmiş] ile ilgili olarak, otomatik düzende bu güzel özelliğe sahiptir, ancak tabi ki eski hedeflerle geriye dönük olarak uyumlu değildir. Oh, ben kendi başıma yapacağım sanırım! :) –

cevap

15

Sen sahip ilk tamamlanma işleyici ayarlamak ve ancak o zaman göndermek animatör vekil. Aksi halde, animasyon başladıktan sonra tamamlama işleyicisini ayarlamayı hemen tetikler ve animasyonun bitmesi için zaman geçmeden sabit kaldırılır.

[NSAnimationContext beginGrouping]; 
    NSAnimationContext.currentContext.duration = animagionDuration; 
    NSAnimationContext.currentContext.completionHandler = ^{[self removeConstraint:collapseConstraint];}; 
    [collapseConstraint.animator setConstant:expandedHeight]; 
    [NSAnimationContext endGrouping]; 

Bu mükemmel çalışıyor, ancak -setConstant: sonra tamamlama işleyicisi ayarlarsanız, animasyon çalıştırmak için bir şansı yoktur: Ben sadece basit bir kod parçası ile bu kontrol ettirin.

+0

Vay, gerçekten işe yaradı. Bahşiş için teşekkürler! –

+0

Hiç de değil, bir süre önce aynı soruna girdim ve bu beni denemeye iten soruydu :) – skh

1

Kendimi bu yüzden bu bir naif analiz olabilir ama bu şeyler ile kulpları alıyorum:

Size belirtiyorsanız geliyor bana ki (senin başka bloğunda) kısıtların özelliklerine bir animasyon ancak, sonra, animasyonu çalıştırma şansı olmadan önce kısıtlama referansını derhal sıfırlamak (potansiyel olarak serbest bırakmak).

Animasyon tamamlama bloğundan içeriden veya tetiklenerek hiddenConstraint öğesini sıfırlamak isteyebilirsiniz. muhtemel olduğu gibi, hatam varsa ben daha iyi :)

+0

Bir görünümün ona eklediğiniz herhangi bir kısıtlamaya sahip olduğunu varsaymak mantıklıdır, bu nedenle kısıtlama 'hiddenConstraint' özelliği ile başvurulmasa bile, yine de görünümün kısıtlama listesiyle başvurulmalıdır. Ayrıca, blokta kullandığınız herhangi bir nesne değişkeninin değerlerini koruduğu için, blokun kendisi tarafından da canlı tutulur. –

+0

Peter'in dediği gibi, 'kısıtlama' güçlü bir referanstır ve blok tarafından yakalanır ve görünüm olmasa bile kısıtlamayı korur. Orta derecede karmaşık bir autolayout'ta yüzlerce kısıtlama vardır ve büyük çoğunluğa yalnızca kendilerine ait olan görünümler tarafından başvurulur. –

+0

Kibar cevaplar çocuklar için teşekkürler. –

3

o düşündüğü için tamamlama işleyicisi hemen tetiklendiğini olmadığı herhangi vardır bana anlamalarına yardımcı olmak için neden bir veya iki kelime takdir edeceğini

Not çalıştırılması gereken animasyonlar. Oluşturduğunuz animasyonun hala görünüme bağlı olduğunu kontrol edip onaylıyorum. Varsayılan olarak, CABasicAnimation, CAAnimation'dan (varsayılan olarak EVET olarak ayarlanır) alınan removedOnCompletion özelliği aracılığıyla tamamlandıktan sonra kendisini kaldırmaya ayarlanmıştır.

Eğer Kabul ediyorum

anim.removedOnCompletion = NO; 
+0

'anim.removedOnCompletion = NO;' ifadesinin herhangi bir etkisi yoktur. Yine de iyi bir öneri. –

12

için, bu oldukça garip ve iyi bir hata olabilir isteyeceksiniz. Bunu kesinlikle bildirirdim çünkü bildiğim kadarıyla, bu , çalışmalıdır.

Ben beginGrouping ve endGrouping tabloların yerine NSAnimationContext sınıf yöntemi +runAnimationGroup:completionHandler: kullanarak çalışmak için bunu elde edebildi:

[NSAnimationContext runAnimationGroup:^(NSAnimationContext* context){ 
    [constraint.animator setConstant:self.width]; 
} completionHandler:^(void){ 
    [theView removeConstraint:constraint]; 
    NSLog(@"completed"); 
}]; 
+0

Ne yazık ki, bu benim kodum üzerinde bir etkisi olmamıştır. Muhtemelen bir radar vereceğim; Bu kesinlikle çalışmak zorunda gibi görünüyor. –

+0

Bu garip. Kesinlikle burada iyi çalışıyor. –

+0

Benim için de çalışıyordu. – stevex