2010-12-27 7 views

risposta

3

iOS non supporta la trasparenza nel presentare una vista modale.

+1

Sì, penso. Fino ad ora iOS non supporta la trasparenza in modale. Grazie per la tua risposta. :) – Rizki

+0

bene, sapendo che non aiuta però –

+0

questo non è corretto, lo faccio con transperancy. – DeyaEldeen

0

Probabilmente si desidera aggiungere un UIView come un overlay alla visualizzazione corrente ma farlo a schermo intero con uno sfondo trasparente o semi-trasparente. Vedere la prima risposta a questa domanda:

disable elements on UIView behind modal UIView

0

Hai bisogno di lavorare all'indietro, sorta di. Carica la tua vista modale, quindi aggiungi tutti i tuoi elementi su di essa "manualmente" come sottoview, in questo modo non saranno nascosti dietro. Sì, è un sacco di codice, ma può essere fatto. L'ho fatto per la riproduzione di film e l'aggiunta di elementi aggiuntivi sullo schermo impostando una dimensione di fotogramma più piccola per il riproduttore di film e lanciando alcuni pulsanti e visualizzazioni di testo attorno ad esso come sottoview. B

10

Okay, presentModalViewController non offre questo comportamento ... tuttavia è ancora possibile. Ho creato una categoria che funziona per me (e spero tu). Come bonus aggiuntivo, previene anche i crash relativi al licenziamento e alla presentazione di viste modali allo stesso tempo!

file di intestazione:

// 
// UIViewController+overView.h 
// Created by Kevin Lohman on 5/30/12. 
// 

#import <UIKit/UIKit.h> 

@interface UIViewController (OverView) 
- (void)presentOverViewController:(UIViewController *)modalViewController animated:(BOOL)animated; 
- (void)dismissOverViewControllerAnimated:(BOOL)animated; 
@end 

Attuazione File:

// 
// UIViewController+overView.m 
// Created by Kevin Lohman on 5/30/12. 
// 

#import "UIViewController+overView.h" 

@implementation UIViewController (OverView) 

#define kUIViewControllerOverViewDismissNotification @"OverViewDismissNotification" 

const float kUIViewControllerOverViewAnimationDuration = 0.75; 
const NSInteger kUIViewControllerOverViewTag = 8008135; // Arbitrary number, so as not to conflict 
- (void)overViewDismissed 
{ 
    [self autorelease]; 
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kUIViewControllerOverViewDismissNotification object:self.view]; 
} 

- (void)presentOverViewController:(UIViewController *)modalViewController animated:(BOOL)animated 
{ 
    UIView *toView = self.view; 

    CGRect finalRect = CGRectIntersection([[UIScreen mainScreen] applicationFrame], self.view.frame); // Make sure it doesn't go under menu bar 
    modalViewController.view.frame = finalRect; 
    modalViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; 
    modalViewController.view.tag = kUIViewControllerOverViewTag+modalViewController.modalTransitionStyle; // Hiding some info here :) 

    if(animated) 
    { 
     switch(modalViewController.modalTransitionStyle) 
     { 
      // Currently only cross dissolve and cover vertical supported... if you add support let me know. 
      case UIModalTransitionStyleCrossDissolve: 
      { 
       float beforeAlpha = modalViewController.view.alpha; 
       modalViewController.view.alpha = 0; 
       [toView addSubview:modalViewController.view]; 
       [UIView animateWithDuration:kUIViewControllerOverViewAnimationDuration animations:^{ 
        modalViewController.view.alpha = beforeAlpha; 
       }]; 
       break; 
      } 
      case UIModalTransitionStyleCoverVertical: 
      default: 
      { 
       modalViewController.view.frame = CGRectMake(modalViewController.view.frame.origin.x, modalViewController.view.frame.size.height, 
                  modalViewController.view.frame.size.width, modalViewController.view.frame.size.height); 
       [toView addSubview:modalViewController.view]; 
       [UIView animateWithDuration:kUIViewControllerOverViewAnimationDuration animations:^{ 
        modalViewController.view.frame = finalRect; 
       }]; 
       break; 
      } 
     } 
    } 
    else { 
     [toView addSubview:modalViewController.view]; 
    } 

    [modalViewController retain]; // Keep it around until we dismiss it. 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(overViewDismissed) name:kUIViewControllerOverViewDismissNotification object:modalViewController.view]; // Release will happen when this notification is posted 
} 

NSInteger transitionStyleForTag(tag) 
{ 
    if (tag >= kUIViewControllerOverViewTag && tag <= kUIViewControllerOverViewTag+UIModalTransitionStylePartialCurl) 
    { 
     return tag-kUIViewControllerOverViewTag; 
    } 
    else { 
     return -1; // Not a Over View 
    } 
} 

- (void)dismissOverViewControllerAnimated:(BOOL)animated 
{ 
    UIView *overView = transitionStyleForTag(self.view.tag) >= 0 ? self.view : nil; // Can dismiss ourselves 
    for(UIView *subview in self.view.subviews) 
    { 
     if(transitionStyleForTag(subview.tag) >= 0) 
      overView = subview; // Keep going, lets dismiss last presented first 
    } 
    if(!overView) return; // None to dismiss 

    if(animated) 
    { 
     switch(transitionStyleForTag(overView.tag)) 
     { 
      // Currently only cross dissolve and cover vertical supported... if you add support let me know. 
      case UIModalTransitionStyleCrossDissolve: 
      { 
       float beforeAlpha = overView.alpha; 
       [UIView animateWithDuration:kUIViewControllerOverViewAnimationDuration animations:^{ 
        overView.alpha = 0; 
       } completion:^(BOOL finished) { 
        [overView removeFromSuperview]; 
        overView.alpha = beforeAlpha; 
        [[NSNotificationCenter defaultCenter] postNotificationName:kUIViewControllerOverViewDismissNotification object:overView]; 
       }]; 
       break; 
      } 
      case UIModalTransitionStyleCoverVertical: 
      default: 
      { 
       [UIView animateWithDuration:kUIViewControllerOverViewAnimationDuration animations:^{ 
        overView.frame = CGRectMake(0, overView.frame.size.height, overView.frame.size.width, overView.frame.size.height); 
       } completion:^(BOOL finished) { 
        [overView removeFromSuperview]; 
        [[NSNotificationCenter defaultCenter] postNotificationName:kUIViewControllerOverViewDismissNotification object:overView]; 
       }]; 
       break; 
      } 
     } 
    } 
    else { 
     [overView removeFromSuperview]; 
     [[NSNotificationCenter defaultCenter] postNotificationName:kUIViewControllerOverViewDismissNotification object:overView]; 
    } 
} 
@end 

e quindi di utilizzare, è sufficiente utilizzare presentOverViewController invece di presentModalViewController e dismissOverViewController invece di dissmissModalViewController.

ci sono un paio di limitazioni:

  1. Devi presentare alla radice più a controller di vista, quindi se si vuole per coprire l'intero schermo e hai un VC all'interno di un UINavigationController, presentalo al controller di navigazione.
  2. Alcuni problemi di rotazione (non ho visto nessuno) su versioni precedenti di iOS (versione 4.0)
  3. Attualmente gestisce solo animazioni Dissolvenza incrociata e Coprire verticali.
+0

Soluzione bella e ordinata, grazie! Due osservazioni però. In primo luogo, il gestore della notifica 'overViewDismissed' rilascia self al posto del controller della vista modale e questo porta al crash. Rimuovere del tutto il codice di notifica addObserver/postNotification e gestire la memoria del controller della vista modale al di fuori dei metodi presente/ignoto. In secondo luogo, '[[UIScreen mainScreen] applicationFrame]' non restituisce sempre la dimensione corretta del frame. Io uso 'self.view.superview.frame' invece (vedi [questa risposta] (http://stackoverflow.com/a/4052442/22764)). –

+0

@VladimirGrigorov hey grazie per la nota, sembra che ci sia una cattiva logica lì. Non ricordo quale base di codice ho inserito, ma immagino di averlo risolto localmente ... se stai ancora compilando/eseguendo una versione fissa da qualche parte, potresti modificare la risposta in base ai tuoi risultati? Potrei cambiarlo (è solo cambiare [auto autorelease] a [autorelease self.parentViewController]? Risky per me di rendere ciecamente il cambiamento :) – BadPirate

+0

Ho già rimosso il codice di notifica come ho dichiarato nel mio commento precedente e quella versione ha superato test ... –

9

La risposta per me era una riga di codice, aggiunto al controller della vista genitore prima di presentare la vista modale regolatore:

self.modalPresentationStyle = UIModalPresentationCurrentContext; 

Questo fermerà vista padre di essere rimosso una volta che la vista modale ha stato aggiunto.

+0

Questo non sembra funzionare per me. –

+0

Non mi ha aiutato. – surfrider

+6

Ma questo funziona self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext; – surfrider

Problemi correlati