2011-08-02 3 views
22

J'ai vu plusieurs questions similaires à cela, mais aucune qui répond à mes besoins spécifiques. Je veux être capable d'écrire une méthode d'assistance générique qui renvoie la taille de trame utilisable maximale pour un UIView, en prenant en compte si l'application a une combinaison de barre d'état, de barre de navigation et/ou de barre d'onglets. le temps.Déterminer par programme la taille de trame maximale utilisable pour un UIView

définition de la méthode serait comme une extension de UIScreen:

+ (CGRect) maximumUsableFrame; 

Obtenir la taille avec ou sans la barre d'état peut être obtenu à partir de la

[UIScreen mainScreen].applicationFrame

propriété, mais je ne peux pas un moyen de déterminer si une barre de navigation ou une barre d'onglets est présente. J'ai pensé à conserver des drapeaux globaux dans mon délégué d'application, mais cela semble vraiment maladroit et empêche le code d'être générique et réutilisable. J'ai également envisagé de passer un UIView en paramètre, d'obtenir la fenêtre de la vue, puis le rootViewController puis de voir si la propriété du contrôleur de navigation est définie. Si oui, vérifiez si le contrôleur de navigation est caché. Tout est très maladroit si vous me demandez.

Toutes les pensées seraient appréciées.

Dave

EDIT: L'intégration des idées de la réponse de Caleb dans le cas où cela est utile à quelqu'un d'autre:

// Extension to UIViewController to return the maxiumum usable frame size for a view 
@implementation UIViewController (SCLibrary) 

- (CGRect) maximumUsableFrame { 

    static CGFloat const kNavigationBarPortraitHeight = 44; 
    static CGFloat const kNavigationBarLandscapeHeight = 34; 
    static CGFloat const kToolBarHeight = 49; 

    // Start with the screen size minus the status bar if present 
    CGRect maxFrame = [UIScreen mainScreen].applicationFrame; 

    // If the orientation is landscape left or landscape right then swap the width and height 
    if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { 
     CGFloat temp = maxFrame.size.height; 
     maxFrame.size.height = maxFrame.size.width; 
     maxFrame.size.width = temp; 
    } 

    // Take into account if there is a navigation bar present and visible (note that if the NavigationBar may 
    // not be visible at this stage in the view controller's lifecycle. If the NavigationBar is shown/hidden 
    // in the loadView then this provides an accurate result. If the NavigationBar is shown/hidden using the 
    // navigationController:willShowViewController: delegate method then this will not be accurate until the 
    // viewDidAppear method is called. 
    if (self.navigationController) { 
     if (self.navigationController.navigationBarHidden == NO) { 

      // Depending upon the orientation reduce the height accordingly 
      if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { 
       maxFrame.size.height -= kNavigationBarLandscapeHeight; 
      } 
      else { 
       maxFrame.size.height -= kNavigationBarPortraitHeight; 
      } 
     } 
    } 

    // Take into account if there is a toolbar present and visible 
    if (self.tabBarController) { 
     if (!self.tabBarController.view.hidden) maxFrame.size.height -= kToolBarHeight; 
    } 
    return maxFrame; 
} 
+1

Si NavigationBar et TabBar sont visibles, vous pouvez trouver des hauteurs de cette façon: 'self.navigationController.navigationBar.frame.size.height,' et 'self.tabBarController.tabBar.frame.size.height'. Pourquoi une variable pour la hauteur des tabulations appelée kToolBarHeight?=) – Alexander

+0

Selon la façon dont vous voulez l'utiliser, au moins dans mon cas, j'ai également mis à jour l'origine de l'image pour le navController afin que je sache exactement où je pourrais positionner ma vue dans le ViewController. Sinon, vous pourriez toujours finir sous la barre de navigation. –

Répondre

7

Je pense que vous mettez votre méthode au mauvais endroit. UIScreen sait à propos de l'écran, mais il ne sait pas (et ne devrait pas) rien savoir sur ce qui est affiché sur l'écran. C'est le contrôleur de vue qui est responsable de la gestion de la vue, c'est donc là que la méthode appartient. De plus, comme le frame max dépend de la configuration d'un contrôleur de vue particulier, il doit s'agir d'une méthode d'instance et non d'une méthode de classe. Je pense que vous devriez ajouter une catégorie à UIViewController avec la méthode:

- (CGRect) maximumUsableFrame; 

Il est encore assez générique, disponible pour tous les contrôleurs de vue, mais en même temps a accès pour afficher les propriétés du contrôleur comme navigationController et tabBarController.

+1

Merci pour les pointeurs tous les bons trucs et fait beaucoup de sens. Je vais écrire l'extension et vous laisser savoir comment je m'entends. –

+2

J'ai ajouté une catégorie au UIViewController et édité ma question originale pour inclure le code et j'apprécierais vos pensées. À bientôt Dave. –

9

Utilisez applicationFrame. [[UIScreen mainScreen] applicationFrame]

Voici comment je l'utilise pour recadrer des éléments dans ma capture d'écran.

Voici un exemple de code.

-(UIImage*) crop20PointsifStatusBarShowsUp 
{ 
    CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame]; //Look at this 
    float sizeOfStatusBarVar= applicationFrame.origin.y; 
    if ([BGMDApplicationsPointers statusBarShowUp]) 
    { 
     CGRect newSize = CGRectMake(0, sizeOfStatusBarVar, self.size.width, self.size.height-sizeOfStatusBarVar); 
     UIImage * newImage = [self cropUIImageWithCGRect:newSize]; 
     return newImage; 
    } 
    else{ 
     return [self copy]; 
    } 
} 
+0

Aucune idée pourquoi ce n'est pas la meilleure réponse. – Isak

0

Pour obtenir ce travail a dû utiliser des bornes d'application et le commutateur d'orientation pour savoir de quel côté la barre d'état est censé être supprimé. Ceci est une copie et un tweak du code publié à l'origine. J'ai fait une application rapide qui exécute cet algorithme à travers les combinaisons d'avoir navbar/tabbar/none avec une barre d'état et cela a fonctionné dans tous les scénarios.

- (CGRect) maxFrame 
{ 
    // Start with the screen size minus the status bar if present 
    CGRect maxFrame = [UIScreen mainScreen].applicationFrame; 

    // the glass screen size 
    CGRect maxBounds = [UIScreen mainScreen].bounds; 


NSLog(@"MaxFrame for %d: (%f, %f, %f, %f)", self.interfaceOrientation, maxFrame.origin.x, maxFrame.origin.y, maxFrame.size.width, maxFrame.size.height); 
NSLog(@"MaxBounds for %d: (%f, %f, %f, %f)", self.interfaceOrientation, maxBounds.origin.x, maxBounds.origin.y, maxBounds.size.width, maxBounds.size.height); 


    // figure out the offset of the status bar 
    CGFloat statusBarOffset; 
    switch (self.interfaceOrientation) { 
     case UIInterfaceOrientationPortrait: 
      statusBarOffset = maxFrame.origin.y; 
     break; 
     case UIInterfaceOrientationPortraitUpsideDown: 
      statusBarOffset = maxBounds.size.height - maxFrame.size.height; 
     break; 
     case UIInterfaceOrientationLandscapeRight: 
     case UIInterfaceOrientationLandscapeLeft: 
      statusBarOffset = maxBounds.size.width - maxFrame.size.width; 
     break; 
    } 

    // If the orientation is landscape left or landscape right then swap the width and height 
    if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { 
     CGFloat temp = maxBounds.size.height; 
     maxBounds.size.height = maxBounds.size.width; 
     maxBounds.size.width = temp; 
    } 

    // apply status bar to the top of the view 
    maxBounds.origin.y = statusBarOffset; 
    maxBounds.size.height -= statusBarOffset; 

    // Take into account if there is a navigation bar present and visible (note that if the NavigationBar may 
    // not be visible at this stage in the view controller's lifecycle. If the NavigationBar is shown/hidden 
    // in the loadView then this provides an accurate result. If the NavigationBar is shown/hidden using the 
    // navigationController:willShowViewController: delegate method then this will not be accurate until the 
    // viewDidAppear method is called) 
    if (self.navigationController && !self.navigationController.navigationBarHidden) { 
     NSLog(@"has nav bar"); 
     maxBounds.size.height -= self.navigationController.navigationBar.frame.size.height; 
     maxBounds.origin.y += self.navigationController.navigationBar.frame.size.height; 
    } 

    // Take into account if there is a toolbar present and visible 
    if (self.tabBarController && !self.tabBarController.view.hidden) { 
     maxBounds.size.height -= self.tabBarController.tabBar.frame.size.height; 
     NSLog(@"has tab bar"); 
    } 

NSLog(@"result for %d: (%f, %f, %f, %f)", self.interfaceOrientation, maxBounds.origin.x, maxBounds.origin.y, maxBounds.size.width, maxBounds.size.height); 
    return maxBounds; 
} 
+0

a dû commenter le maxBounds.origin.y = statusBarOffset; et maxBounds.origin.y + = self.navigationController.navigationBar.frame.size.height; dans une application différente, cela a été utilisé dans. –

Questions connexes