¿Alguien sabe cómo puedo usar mi subclase personalizada UINavigationBar
si creo una instancia mediante UINavigationController
programación (sin IB)?
Arrastra un UINavigationController
en IB y muéstrame debajo de la barra de navegación y usando el Inspector de identidad puedo cambiar el tipo de clase y establecer mi propia subclase, UINavigationBar
pero programáticamente no puedo, la navigationBar
propiedad del controlador de navegación es de solo lectura ...
¿Qué debo hacer para personalizar la barra de navegación mediante programación? ¿IB es más "poderoso" que el "código"? Creía que todo lo que se puede hacer en IB también se puede hacer mediante programación.
Respuestas:
No es necesario que juegue con el XIB, simplemente use KVC.
fuente
Desde iOS5, Apple proporciona un método para hacer esto directamente. Referencia
fuente
A partir de iOS 4, puede usar la
UINib
clase para ayudar a resolver este problema.UINavigationBar
subclase personalizada .UINavigationController
como único objeto.UINavigationController
'sUINavigationBar
para su subclase personalizada.[navController setViewcontrollers[NSArray arrayWithObject:myRootVC]];
[navController pushViewController:myRootVC];
En codigo:
Ahora tienes una
UINavigationController
con tu costumbreUINavigationBar
.fuente
Por lo que puedo decir, a veces es necesario subclasificar UINavigationBar, para hacer un rediseño no estándar. A veces es posible evitar tener que hacerlo mediante el uso de categorías , pero no siempre.
Actualmente, hasta donde yo sé, la única forma de configurar un UINavigationBar personalizado dentro de un UIViewController es a través de IB (es decir, a través de un archivo); probablemente no debería ser así, pero por ahora, debemos vivir con él.
Esto suele estar bien, pero a veces utilizar IB no es realmente factible.
Entonces, vi tres opciones:
La opción 1 fue inviable (o al menos demasiado molesta) para mí en este caso, ya que necesitaba crear el UINavigationController programáticamente, 2 es un poco peligrosa y más una opción de último recurso en mi opinión, así que elegí la opción 3.
Mi enfoque fue crear un archivo de 'plantilla' de un UINavigationController, y desarchivarlo, devolviéndolo en formato
initWithRootViewController
.Así es cómo:
En IB, creé un UINavigationController con el conjunto de clases apropiado para UINavigationBar.
Luego, tomé el controlador existente y guardé una copia archivada usando
+[NSKeyedArchiver archiveRootObject:toFile:]
. Acabo de hacer esto dentro del delegado de la aplicación, en el simulador.Luego utilicé la utilidad 'xxd' con el indicador -i, para generar código c desde el archivo guardado, para incrustar la versión archivada en mi subclase (
xxd -i path/to/file
).Dentro
initWithRootViewController
desarchivo esa plantilla, y me pongo al resultado del desarchivar:Luego, puedo simplemente tomar una nueva instancia de mi subclase UIViewController que tiene configurada la barra de navegación personalizada:
Esto me da un UITableViewController modal con una barra de navegación y una barra de herramientas configuradas, y con la clase de barra de navegación personalizada en su lugar. No tuve que hacer ningún reemplazo de método ligeramente desagradable, y no tengo que perder el tiempo con las puntas cuando realmente solo quiero trabajar programáticamente.
Me gustaría ver el equivalente de
+layerClass
dentro de UINavigationController+navigationBarClass
, pero por ahora esto funciona.fuente
Yo uso la "opción 1"
Cree un archivo nib que solo contenga UINavigationController. Y establezca la clase UINavigationBar en mi clase personalizada.
fuente
La solución de Michael funciona, pero puede evitar NSKeyedArchiver y la utilidad 'xxd'. Simplemente subclase UINavigationController y anule
initWithRootViewController
, cargando su NIB NavigationController personalizado directamente:fuente
Actualización: el uso
object_SetClass()
ya no funciona como si iOS5 GM. Se ha agregado una solución alternativa a continuación.Use NSKeyedUnarchiver para configurar manualmente la clase de desarchivar para la barra de navegación.
Nota: esta solución original solo funciona antes de iOS5:
Hay una gran solución, que publiqué aquí : inyecte la subclase navBar directamente en su vista
UINavigationController
:fuente
Un escenario que encontré en el que necesitamos usar una subclase en lugar de una categoría es establecer el color de fondo de la barra de navegación con la imagen del patrón, porque en iOS5 sobrescribir drawRect usando la categoría ya no funciona. Si desea admitir ios3.1-5.0, la única forma de hacerlo es subclasificar la barra de navegación.
fuente
Estos métodos de categoría son peligrosos y no para principiantes. Además, la complicación con iOS4 e iOS5 son diferentes, lo que hace que esta sea un área que puede causar errores para muchas personas. Aquí hay una subclase simple que uso que es compatible con iOS4.0 ~ iOS6.0 y es muy simple.
.h
.metro
fuente
No se recomienda subclasificar la
UINavigationBar
clase. La forma preferida de personalizar la barra de navegación es establecer sus propiedades para que aparezca como desee y usar vistas personalizadas dentro de UIBarButtonItems junto con un delegado para obtener el comportamiento deseado.¿Qué estás intentando hacer que necesite subclases?
Además, no creo que IB esté reemplazando la barra de navegación. Estoy bastante seguro de que simplemente no muestra el predeterminado y tiene su barra de navegación personalizada como una subvista. Si llama a UINavigationController.navigationBar, ¿obtiene una instancia de su barra?
fuente
Si desea crear una subclase de navBar solo para cambiar la imagen de fondo, no es necesario hacerlo en iOS 5. Habrá un método como este setBackgroundImage
fuente
setBackgroundImage:forBarMetrics:
como se describe aquí: developer.apple.com/library/IOS/#documentation/UIKit/Reference/…Además del comentario de obb64, terminé usando su truco con
setViewControllers:animated:
para configurar el controlador comorootController
elnavigationController
cargado desde la punta. Aquí está el código que estoy usando:fuente