¿Cómo agregar un botón derecho a un UINavigationController?

191

Estoy tratando de agregar un botón de actualización a la barra superior de un controlador de navegación sin éxito.

Aquí está el encabezado:

@interface PropertyViewController : UINavigationController {

}

Así es como estoy tratando de agregarlo:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:@"Show" style:UIBarButtonItemStylePlain
                                          target:self action:@selector(refreshPropertyList:)];      
        self.navigationItem.rightBarButtonItem = anotherButton;
    }
    return self;
}
Artilheiro
fuente

Respuestas:

362

Intenta hacerlo en viewDidLoad. En general, debe diferir todo lo que pueda hasta ese punto de todos modos, cuando se inicia un UIViewController, aún puede pasar bastante tiempo antes de que se muestre, no tiene sentido hacer el trabajo temprano y bloquear la memoria.

- (void)viewDidLoad {
  [super viewDidLoad];

  UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:@"Show" style:UIBarButtonItemStylePlain target:self action:@selector(refreshPropertyList:)];          
  self.navigationItem.rightBarButtonItem = anotherButton;
  // exclude the following in ARC projects...
  [anotherButton release];
}

En cuanto a por qué no funciona actualmente, no puedo decir con 100% de certeza sin ver más código, pero suceden muchas cosas entre init y la carga de la vista, y es posible que esté haciendo algo que hace que el elemento de navegación se restablezca en Entre.

Louis Gerbarg
fuente
45
Si está haciendo esto fuera de la subclase UINavigationController, se referiría de esta manera: someNavController.topLevelController.navigationItem.rightBarButtonItem = anotherButton
ransomweaver
2
Estaba implementando la solución sugerida y mi aplicación seguía fallando hasta que me di cuenta de que el nombre del método @selector tenía que terminar en dos puntos (:).
Stealth
10
Incluso dentro del método viewDidLoad de UINavigationContoller, tuve que llamarlo comoself.topViewController.navigationItem.leftBarButtonItem = nextButton;
Joseph
¡Gracias! @ Joseph, Tu aclaración me salvó. (y) :)
Prasanna
38

Intente agregar el botón al elemento de navegación del controlador de vista que se va a insertar en esta PropertyViewControllerclase que ha creado.

Es decir:

MainViewController *vc = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[infoButton addTarget:self action:@selector(showInfo) forControlEvents:UIControlEventTouchUpInside];
vc.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:infoButton] autorelease];

PropertyViewController *navController = [[PropertyViewController alloc] initWithRootViewController:vc];

Ahora, este infoButton que se ha creado programáticamente aparecerá en la barra de navegación. La idea es que el controlador de navegación recoja su información de visualización (título, botones, etc.) de la UIViewControllerque está a punto de mostrar. En realidad, no agrega botones y tal directamente al UINavigationController.

Adán
fuente
2
Establecer el rightBarButtonItem directamente en el UINavigationController no funcionó para mí (como lo propuso Louis Gerbarg anteriormente). ¡En lugar de configurar el elemento directamente en el UIViewController como Adem sugiere que funcionó!
leviatán
44
¡+1 para "Intente agregar el botón al elemento de navegación del controlador de vista que se va a presionar" !
Kjuly
25

Parece que algunas personas (como yo) pueden venir aquí buscando cómo agregar un botón de barra de navegación en el Creador de interfaces. La respuesta a continuación muestra cómo hacerlo.

Agregue un controlador de navegación a su guión gráfico

Seleccione su controlador de vista y luego en el menú Xcode elija Editor> Incrustar en> Controlador de navegación .

ingrese la descripción de la imagen aquí

Alternativamente, puede agregar uno UINavigationBardesde la Biblioteca de objetos.

Agregar un elemento de botón de barra

Arrastre a UIBarButtonItemdesde la Biblioteca de objetos a la barra de navegación superior.

ingrese la descripción de la imagen aquí

Debe tener un aspecto como este:

ingrese la descripción de la imagen aquí

Establecer los atributos

Puede hacer doble clic en "Elemento" para cambiar el texto a algo como "Actualizar", pero hay un icono real para Actualizar que puede usar. Simplemente seleccione los atributos para el inspector UIBarButtonItemy de artículo Sistema elija Actualizar .

ingrese la descripción de la imagen aquí

Eso le dará el icono de actualización predeterminado.

ingrese la descripción de la imagen aquí

Agregar una acción de IB

Controle el arrastre desde UIBarButtonItemal Controlador de vista para agregar un @IBAction.

class ViewController: UIViewController {

    @IBAction func refreshBarButtonItemTap(sender: UIBarButtonItem) {
        
        print("How refreshing!")
    }
    
}

Eso es.

Suragch
fuente
Lo siento, no puedo entender lo que estás hablando. Intente hacer una nueva pregunta con una imagen que ilustre de qué está hablando. Luego agregue un enlace aquí.
Suragch
@Suragch, ¿cómo puedo hacer lo mismo con los archivos xib en lugar de los guiones gráficos? , gracias
Cristian Chaparro A.
@CristianChaparroA. Por lo general, los archivos xib son para vistas únicas y la barra de navegación (que aloja los elementos del botón de la barra) es para múltiples vistas. Nunca he usado un xib con elementos de botones de barra. Puede intentar hacer una nueva pregunta y luego vincularla aquí.
Suragch
14

Hay un botón de sistema predeterminado para "Actualizar":

- (void)viewDidLoad {
    [super viewDidLoad];

    UIBarButtonItem *refreshButton = [[[UIBarButtonItem alloc] 
                            initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
                            target:self action:@selector(refreshClicked:)] autorelease];
    self.navigationItem.rightBarButtonItem = refreshButton;

}

- (IBAction)refreshClicked:(id)sender {

}
Manni
fuente
11

Puedes usar esto:

C objetivo

UIBarButtonItem *rightSideOptionButton = [[UIBarButtonItem alloc] initWithTitle:@"Right" style:UIBarButtonItemStylePlain target:self action:@selector(rightSideOptionButtonClicked:)];          
self.navigationItem.rightBarButtonItem = rightSideOptionButton;

Rápido

let rightSideOptionButton = UIBarButtonItem()
rightSideOptionButton.title = "Right"
self.navigationItem.rightBarButtonItem = rightSideOptionButton
Vandit Mehta
fuente
6
-(void) viewWillAppear:(BOOL)animated
{

    UIButton *btnRight = [UIButton buttonWithType:UIButtonTypeCustom];
    [btnRight setFrame:CGRectMake(0, 0, 30, 44)];
    [btnRight setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
    [btnRight addTarget:self action:@selector(saveData) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *barBtnRight = [[UIBarButtonItem alloc] initWithCustomView:btnRight];
    [barBtnRight setTintColor:[UIColor whiteColor]];
    [[[self tabBarController] navigationItem] setRightBarButtonItem:barBtnRight];

}
Gaurav Gilani
fuente
¿Alguien puede decirme si hay algún daño al hacerlo en ViewWillAppear en lugar de ViewDidLoad
Niranjan Molkeri
6

Para Swift 2:

self.title = "Your Title"

var homeButton : UIBarButtonItem = UIBarButtonItem(title: "LeftButtonTitle", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("yourMethod"))

var logButton : UIBarButtonItem = UIBarButtonItem(title: "RigthButtonTitle", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("yourMethod"))

self.navigationItem.leftBarButtonItem = homeButton
self.navigationItem.rightBarButtonItem = logButton
fandro
fuente
Recomendaría usar el nuevo selector swift2: #selector (classname.functionname)
Emptyless
5

Aquí está la solución en Swift (configure las opciones según sea necesario):

var optionButton = UIBarButtonItem()
optionButton.title = "Settings"
//optionButton.action = something (put your action here)
self.navigationItem.rightBarButtonItem = optionButton
vontell
fuente
4

¿Por qué son subclases UINavigationController? No hay necesidad de subclasificarlo si todo lo que necesita hacer es agregarle un botón.

Configure una jerarquía con un UINavigationControlleren la parte superior, y luego en el viewDidLoad:método del controlador de vista raíz : configure el botón y adjúntelo al elemento de navegación llamando

[[self navigationItem] setRightBarButtonItem:myBarButtonItem];
Jasarien
fuente
1
Esa es una buena pregunta. Lo que intento hacer es en realidad un patrón de diseño muy común, que es un controlador de pestañas básico con un controlador de navegación para cada pestaña. Si hay una mejor manera, estoy abierto a sugerencias. Tal vez debería hacer esa pregunta también.
Artilheiro
4

Puedes probar

self.navigationBar.topItem.rightBarButtonItem = anotherButton;
usuario2999133
fuente
Funcionó como un encanto :)
Saurabh Bhatia
3

Swift 4:

override func viewDidLoad() {
    super.viewDidLoad()

    navigationItem.leftBarButtonItem = UIBarButtonItem(title: "tap me", style: .plain, target: self, action: #selector(onButtonTap))
}

@objc func onButtonTap() {
    print("you tapped me !?")
}
ergunkocak
fuente
Simplemente use navigationItem.rightBarButtonItem si desea el botón del lado derecho
Ghanshyam Bagul
2
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 110, 50)];
view.backgroundColor = [UIColor clearColor];

UIButton *settingsButton =  [UIButton buttonWithType:UIButtonTypeCustom];
[settingsButton setImage:[UIImage imageNamed:@"settings_icon_png.png"] forState:UIControlStateNormal];
[settingsButton addTarget:self action:@selector(logOutClicked) forControlEvents:UIControlEventTouchUpInside];
[settingsButton setFrame:CGRectMake(40,5,32,32)];
[view addSubview:settingsButton];

UIButton *filterButton =  [UIButton buttonWithType:UIButtonTypeCustom];
[filterButton setImage:[UIImage imageNamed:@"filter.png"] forState:UIControlStateNormal];
[filterButton addTarget:self action:@selector(openActionSheet) forControlEvents:UIControlEventTouchUpInside];
[filterButton setFrame:CGRectMake(80,5,32,32)];
[view addSubview:filterButton];



self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:view];
Sandeep
fuente
2

Intenta esto, funciona para mí.

Barra de navegación y también imagen de fondo agregada al botón derecho.

 UIBarButtonItem *Savebtn=[[UIBarButtonItem alloc]initWithImage:[[UIImage    
 imageNamed:@"bt_save.png"]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] 
 style:UIBarButtonItemStylePlain target:self action:@selector(SaveButtonClicked)];
 self.navigationItem.rightBarButtonItem=Savebtn;
Jaywant Khedkar
fuente
0
    UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(add:)];
self.navigationItem.rightBarButtonItem = rightBarButtonItem;
Mahesh Aswathanarayana
fuente
0
- (void)viewWillAppear:(BOOL)animated
{    
    [self setDetailViewNavigationBar];    
}
-(void)setDetailViewNavigationBar
{
    self.navigationController.navigationBar.tintColor = [UIColor purpleColor];
    [self setNavigationBarRightButton];
    [self setNavigationBarBackButton];    
}
-(void)setNavigationBarBackButton// using custom button 
{
   UIBarButtonItem *leftButton = [[UIBarButtonItem alloc] initWithTitle:@"  Back " style:UIBarButtonItemStylePlain target:self action:@selector(onClickLeftButton:)];          
   self.navigationItem.leftBarButtonItem = leftButton;    
}
- (void)onClickLeftButton:(id)sender 
{
   NSLog(@"onClickLeftButton");        
}
-(void)setNavigationBarRightButton
{

  UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:@"Show" style:UIBarButtonItemStylePlain target:self action:@selector(onClickrighttButton:)];          
self.navigationItem.rightBarButtonItem = anotherButton;   

}
- (void)onClickrighttButton:(id)sender 
{
   NSLog(@"onClickrighttButton");  
}
tv.ashvin
fuente
0
    self.navigationItem.rightBarButtonItem =[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshData)];



}

-(void)refreshData{
    progressHud= [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
    [progressHud setLabelText:@"拼命加载中..."];
    [self loadNetwork];
}
Gank
fuente
0

Debes agregar tu barButtonItem en el - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animatedmétodo.

Retik
fuente
0

Simplemente copie y pegue este código Objective-C.

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self addRightBarButtonItem];
}
- (void) addRightBarButtonItem {
    UIButton *btnAddContact = [UIButton buttonWithType:UIButtonTypeContactAdd];
    [btnAddContact addTarget:self action:@selector(addCustomerPressed:) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:btnAddContact];
    self.navigationItem.rightBarButtonItem = barButton;
}

#pragma mark - UIButton
- (IBAction)addCustomerPressed:(id)sender {
// Your right button pressed event
}
Vivek
fuente
Estoy tratando de ayudar
Vivek
0

Este problema puede ocurrir si eliminamos el controlador de vista o intentamos agregar un nuevo controlador de vista dentro del generador de interfaces (main.storyboard). Para solucionar este problema, se requiere agregar "Elemento de navegación" dentro del nuevo controlador de vista. A veces sucede que creamos una nueva pantalla de controlador de vista y no se conecta al "Elemento de navegación" automáticamente.

  1. Vaya al main.storyboard.
  2. Seleccione esa nueva vista Controlador.
  3. Ir al esquema del documento.
  4. Verifique ver el contenido del controlador.
  5. Si el nuevo controlador de vista no tiene un elemento de navegación, copie el elemento de navegación del controlador de vista anterior y péguelo en el nuevo controlador de vista.
  6. guardar y limpiar el proyecto.
NilamK
fuente
0

También puedes agregar varios botones usando rightBarButtonItems

-(void)viewDidLoad{

    UIBarButtonItem *button1 = [[UIBarButtonItem alloc] initWithTitle:@"button 1" style:UIBarButtonItemStylePlain target:self action:@selector(YOUR_METHOD1:)];
    UIBarButtonItem *button2 = [[UIBarButtonItem alloc] initWithTitle:@"button 2" style:UIBarButtonItemStylePlain target:self action:@selector(YOUR_METHOD2:)];

    self.navigationItem.rightBarButtonItems = @[button1, button2];
}
yoAlex5
fuente
-1

@Artilheiro: Si es un proyecto basado en la navegación, puede crear BaseViewController. Todas las demás vistas heredarán esta BaseView. En BaseView, puede definir métodos genéricos para agregar el botón derecho o cambiar el texto del botón izquierdo.

ex:

@interface BaseController: UIViewController {

} - (vacío) setBackButtonCaption: (NSString *) caption;

(nulo) setRightButtonCaption: (NSString *) caption selectot: (SEL) selector;

@end // En BaseView.M

(nulo) setBackButtonCaption: (NSString *) caption {

UIBarButtonItem *backButton =[[UIBarButtonItem alloc] init];

backButton.title= caption;
self.navigationItem.backBarButtonItem = backButton;
[backButton release];

} - (vacío) setRightButtonCaption: (NSString *) caption selectot: (SEL) selector {

  UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] init];
rightButton.title = caption;

rightButton.target= self;

[rightButton setAction:selector];

self.navigationItem.rightBarButtonItem= rightButton;

[rightButton release];

}

Y ahora, en cualquier vista personalizada, implemente esta vista base, llame a los métodos:

@interface LoginView: BaseController {

En algún método, llame al método base como:

SEL sel = @selector (switchToForgotPIN);

[super setRightButtonCaption: @ "Olvidé mi PIN" selectot: sel];

iPhoneDev
fuente