9

Bir Facebook POP animasyonlu geçişi gerçekleştirmek için mevcutViewController ve özel modalPresentationStyle kullanarak bir UIViewController sunumu yapıyorum.Autolayout ile Merkezleme Modal Görünümü

Modelin görünümü tamamen dinamiktir, kodda Autolayout kısıtlamaları kullanılarak tanımlanmıştır. Modalın arkasına xib/storyboard yoktur.

Ekranda merkezlemek için model görünümünü alamıyorum! Autolayout yeterli değildir, çünkü kısıtlamalar eklemek için süper bir görünüm yoktur!

My başvuru kodu (bir FB POP kod örneği alınmıştır) aşağıdaki gibidir:

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext 
{ 
    UIView *fromView = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view; 
    fromView.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed; 
    fromView.userInteractionEnabled = NO; 

    UIView *dimmingView = [[UIView alloc] initWithFrame:fromView.bounds]; 
    dimmingView.backgroundColor = [UIColor colorWithRed:(24/255.0) green:(42/255.0) blue:(15/255.0) alpha:1.0]; 
    dimmingView.layer.opacity = 0.0; 

    UIView *toView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view; 
    toView.frame = CGRectMake(0, 
           0, 
           CGRectGetWidth(transitionContext.containerView.bounds) - 104.f, 
           CGRectGetHeight(transitionContext.containerView.bounds) - 320.f); 
    toView.center = CGPointMake(transitionContext.containerView.center.x, -transitionContext.containerView.center.y); 

    [transitionContext.containerView addSubview:dimmingView]; 
    [transitionContext.containerView addSubview:toView]; 

    POPSpringAnimation *positionAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY]; 
    positionAnimation.toValue = @(transitionContext.containerView.center.y); 
    positionAnimation.springBounciness = 10; 
    [positionAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) { 
     [transitionContext completeTransition:YES]; 
    }]; 

    POPSpringAnimation *scaleAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; 
    scaleAnimation.springBounciness = 20; 
    scaleAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(1.2, 1.4)]; 

    POPBasicAnimation *opacityAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity]; 
    opacityAnimation.toValue = @(0.2); 

    [toView.layer pop_addAnimation:positionAnimation forKey:@"positionAnimation"]; 
    [toView.layer pop_addAnimation:scaleAnimation forKey:@"scaleAnimation"]; 
    [dimmingView.layer pop_addAnimation:opacityAnimation forKey:@"opacityAnimation"]; 
} 

Bu güzel çalışıyor, ancak ben dinamik olarak gerçek görünüm boyutunu gerek (bazen kalıcı olacak dört satırlık metin ve iki düğme, vb. Bunu başarmak için VC alt sınıfında translatesAutoresizingMaskIntoConstraints = NO ayarlamam gerekiyor. Bu, sunum animatöründe yaptığım çerçeve ortalamasını açıkça reddediyor.

Sonuç, ekranın sol kenarına yapışmış bir modeldir; merakla, kendisini dikey olarak değil, yatay olarak ortalar. Görsel olarak, bu (siyah kareler af Ben yasal amaçlarla bunu yapmak zorunda) şuna benzer:

screesshot

bariz çözüm görünümü merkezleri bir görünüm kısıtlama eklemek olacaktır. Sorun yok, değil mi?

Ama bunu nereye eklerim? view.superview sıfırdır; süper görüş yok Özel bir 'superview' özelliği oluşturmayı ve onu ayarlamayı denedim, ancak autolayout, görünüm hiyerarşisinin (sunum vc'sinin) dışında bir görünümü nasıl kullanacağını bilmez. Bu benim bakış hiyerarşi açıklamalı, neye benzediği: Görünüşe göre doğrudan UITransitionView erişmek gerekmiyor

enter image description here

. UIWindow'daki kısıtlamaların etkisi yoktur.

Herhangi bir tavsiyesi olan var mı? Bu tür şeylerle nasıl başa çıkıyorsunuz?

+0

Aslında çözüm için yok ama ben size bu durumda ne yapacağımı söyleyeyim: ** Herhangi bir Autolayout ** 'ı yorumlayın, ** CGRectMake ile pozisyonu ayarlayın (**. Bir şey daha: Bu soruyu nasıl yapılandırdığınızı anlatmak zor. iyi şanslar – carlodurso

+0

Bu yakalama-22. Otomatik düzen kullanmam gerekiyor, çünkü görünüm tamamen dinamik olmalı. – cdstamper

cevap

3

programlı can animateTranisition yönteminizdeki containerView'den toView'e bir ortalama kısıtlaması ekleyin:

(Swift'de, ancak fikir edinebilmeniz gerekir ...)

containerView.addSubview(toView) 

let centerXLayoutConstraint = NSLayoutConstraint(item: toView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: containerView, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0) 
let centerYLayoutConstraint = NSLayoutConstraint(item: toView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: containerView, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0) 

containerView.addConstraint(centerXLayoutConstraint) 
containerView.addConstraint(centerYLayoutConstraint) 

Bunu denediğimde, kapsayıcıya göreli olarak boyutlandırmak için toView öğesine genişlik ve yükseklik kısıtlamaları ekledim. Çalıştı - sorun yok.

Ayrıca, kendi kendine boyutlandırma toView ile çalışması gerektiğini düşünüyorum. IntrinsicSize'i toView sınıfınızda geçersiz kılmanız ve/veya kısıtlamalarını güncellemek için zorlayarak oynamanız gerekebilir.

animateTransition olarak
+0

MÜKEMMEL çalışır. Konteynere doğrudan erişime izin verilmediğine dair biraz endişeliyim ... ama bu şimdilik bir çözüm. Teşekkürler! – cdstamper

+0

Rica ederim! Sevindim, senin için çalıştı! Evet, görüntü konteynırındaki kısıtlamaları merak ediyorum. En azından alt görüntü ekleyebilmeniz gerekiyor. Belki de kısıtlama animateTransition sırasında durumuna (boyut, konum vb.) Güvenmekle ilgili daha fazladır? –

+0

Çalışıyor, göndereceğim ve ne olacağını göreceğim. Reddedilirse birkaç ay içinde güncellenir! – cdstamper

2

Bunu deneyebilir misiniz?

Model penceresi görünümünüzü UIView alt sınıfı olarak bildirin ve didMoveToSuperView'u uygulayın. herhangi Superview eklendiğinde

- (void)didMoveToSuperview { 
    UIView *superView = self.superview; 

    if(superView == nil) { 
     return; 
    } 

    [superView addConstraint:[NSLayoutConstraint constraintWithItem:self 
                  attribute:NSLayoutAttributeCenterX 
                  relatedBy:NSLayoutRelationEqual 
                  toItem:superView 
                  attribute:NSLayoutAttributeCenterX 
                 multiplier:1.0 
                  constant:0]]; 
    [superView addConstraint:[NSLayoutConstraint constraintWithItem:self 
                  attribute:NSLayoutAttributeCenterY 
                  relatedBy:NSLayoutRelationEqual 
                  toItem:superView 
                  attribute:NSLayoutAttributeCenterY 
                 multiplier:1.0 
                  constant:0]]; 

    // [superView layoutIfNeeded]; // If this does not work, try uncomment this. 
} 

Bu kendini otomatik merkezleme yapmak gerekir.

Ayrıca, translatesAutoresizingMaskIntoConstraints = NO ve tüm genişlik/yükseklik kısıtlamalarına da ihtiyacınız olduğunu söyleyebiliriz. Ancak, UITransitionView ile test yapmadım. Belki de bu positionAnimation ile çakışıyor.

DÜZENLEME: 2014/09/22 yerine, görünümü kendisini modal autoLayout kısıtlamaları kullanmanın

, sanatranslatesAutoresizingMaskIntoConstraints = NO olmadan systemLayoutSizeFittingSize: yöntemi kullanmak gerektiğini düşünüyorum.

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext 
{ 
    // ...snip 

    UIView *toView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view; 

    toView.translatesAutoresizingMaskIntoConstraints = YES; // To clarify. You don't need this line because this is the default. 

    CGSize sysSize = [toView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; 
    toView.bounds = CGRectMake(0, 0, sysSize.width, sysSize.height); 
    toView.center = CGPointMake(transitionContext.containerView.center.x, -transitionContext.containerView.center.y); 
    toView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin; 

    // ...snip 

} 

ve (onun içeriği değiştirerek bir yan etkisi olarak) ekran sonra modal görünümü boyutlandırmak istiyorsanız, modal görünümlerde kod aşağıdaki gibi UIViewController alt sınıf yapın:

- (void)yourAppMethod { 
    NSString *message = @""; // <- as u like 
    UILabel *label = self.messageLabel; 
    label.text = message; 
    [self resizeViewIfNeeded]; // <- this will resize self.view 
} 

- (void)resizeViewIfNeeded { 
    CGSize sysSize = [self.view systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; 
    if(!CGSizeEqualToSize(sysSize, self.view.bounds.size)) { 
     self.view.bounds = CGRectMake(0, 0, sysSize.width, sysSize.height); 
    } 
} 
+0

UIView alt sınıfına değişemiyorum, bir VC olmalı . Geçiş konteynır görünümünde kısıtlamalar ayarlama hile yaptı! Teşekkürler için teşekkürler tho. – cdstamper

0

: Eğer [öz addConstraints] gibi özel yöntemini çağırabilirsiniz hiyerarşiye için görüşlerinizi eklemek ve daha sonra böyle bir şey yapmak kez:

- (void)addConstraints 
    { 
     [self.toView setTranslatesAutoresizingMaskIntoConstraints:NO]; 
     [self.dimmingView setTranslatesAutoresizingMaskIntoConstraints:NO]; 

     [self.containerView addConstraint:[NSLayoutConstraint constraintWithItem:self.toView 
                     attribute:NSLayoutAttributeCenterX 
                     relatedBy:NSLayoutRelationEqual 
                      toItem:self.containerView 
                     attribute:NSLayoutAttributeCenterX 
                     multiplier:1 
                     constant:0]]; 
     [self.containerView addConstraint:[NSLayoutConstraint constraintWithItem:self.toView 
                     attribute:NSLayoutAttributeCenterY 
                     relatedBy:NSLayoutRelationEqual 
                      toItem:self.containerView 
                     attribute:NSLayoutAttributeCenterY 
                     multiplier:1 
                     constant:0]]; 
     NSDictionary *views = @{@"dimmingView" : self.dimmingView}; 
     [self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[dimmingView]|" 
                        options:0 
                        metrics:nil 
                        views:views]]; 
     [self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[dimmingView]|" 
                        options:0 
                        metrics:nil 
                        views:views]]; 
}