Determinar mediante programación la máxima utilizable tamaño de marco para una UIView

He visto varias preguntas similares a esta, pero ninguno de ellos se dirige a mi necesidad específica. Quiero ser capaz de escribir un genérico ayudante método que devuelve la máxima utilizable tamaño de marco para una UIView, teniendo en cuenta si la aplicación tiene una combinación de una barra de estado, barra de navegación y/o la ficha de la barra de como me encuentro haciendo esto todo el tiempo.

Definición de método sería como una extensión de UIScreen:

+ (CGRect) maximumUsableFrame;

Conseguir el tamaño con o sin la barra de estado puede ser obtenido de la

[UIScreen mainScreen].applicationFrame

de la propiedad, pero no puedo encontrar una manera de determinar si hay una barra de navegación o la barra de pestañas presente. He pensado acerca de mantener algunos indicadores globales en mi app delegado, pero este parece muy torpe y se detiene el código genérico y re-utilizable. También he considerado pasando un UIView como un parámetro, obteniendo la vista de la ventana, entonces la rootViewController y luego ver si el controlador de navegación se establece la propiedad. Si es así, a continuación, comprobar si el controlador de navegación está oculto. Todo muy torpe, si usted me pregunta.

Alguna idea se agradece.

Dave

EDIT: la Incorporación de las ideas de Caleb respuesta en este caso es de utilidad a alguien más:

//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;
}
  • Si NavigationBar y TabBar son visibles, usted puede encontrar alturas de esta manera:self.navigationController.navigationBar.frame.size.height; y self.tabBarController.tabBar.frame.size.height. Por qué variable para tabbar la altura de la llama kToolBarHeight? =)
  • Dependiendo de cómo desee utilizar este servicio, al menos en mi caso, también he actualizado el marco origen de la navController así que sabía exactamente donde yo podría posición de mi punto de vista en el ViewController. De lo contrario, usted todavía podría terminar bajo la barra de navegación.

3 Kommentare

  1. 7

    Creo que usted está poniendo su método en el lugar equivocado. UIScreen sabe acerca de la pantalla, pero no (y no debe) saber nada acerca de lo que se muestra en la pantalla. Es el controlador de vista de que es el responsable de administrar la vista, así que aquí es donde el método pertenece. Además, ya que la máxima de fotogramas depende de la configuración de un controlador de vista, este debe ser un método de instancia y no a un método de clase. Creo que se debe agregar una categoría UIViewController con el método:

    - (CGRect) maximumUsableFrame;

    Es todavía bastante genérica, disponible para todos los de la vista de los controladores, pero al mismo tiempo tiene acceso a la visualización de las propiedades del controlador como navigationController y tabBarController.

    • Gracias por los punteros de todas las cosas buenas y hace un montón de sentido. Va a escribir la extensión y hacerle saber cómo me va.
    • Han añadido una categoría a la UIViewController y editado mi pregunta original para incluir el código y agradecería sus pensamientos. Saludos Dave.
  2. 9

    Uso applicationFrame. [[UIScreen mainScreen] applicationFrame]

    Así es como yo lo uso para cultivos alimenticios en mi captura de pantalla.

    Aquí está el código de ejemplo.

    -(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];
        }
    }
    • Ni idea de por qué esto no es la respuesta.
  3. 0

    Para conseguir que esto funcione, tuvo que utilizar la aplicación de los límites y la orientación del interruptor de averiguar de qué lado de la barra de estado se debía eliminar. Esto es un copia y tweak del publicado originalmente código. Hice una rápida aplicación que se ejecuta este algoritmo a través de las combinaciones de tener navbar/tabbar/ninguno con una barra de estado y trabajó en todos los escenarios.

    - (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;
    }
    • tenía que comentar la maxBounds.origen.y = statusBarOffset; y maxBounds.origen.y += self.navigationController.navigationBar.marco.tamaño.altura; en una aplicación diferente esto fue usado.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea