UIBarButtonItem na barra de navegação programaticamente?

135

Estou procurando uma solução há algum tempo, mas não a tenho. por exemplo, uma solução é

 self.navigationItem.setRightBarButtonItem(UIBarButtonItem(barButtonSystemItem: .Stop, target: self, action: nil), animated: true)

Este código adicionará um botão com a imagem "stop". Assim, existem outras soluções com "pesquisa", atualização "etc." E se eu quiser adicionar um botão programaticamente com a imagem que eu quero?

Rahul Sonvane
fonte

Respostas:

342

Imagem de botão personalizada sem definir a moldura do botão:

Você pode usar init(image: UIImage?, style: UIBarButtonItemStyle, target: Any?, action: Selector?)para inicializar um novo item usando a imagem especificada e outras propriedades.

let button1 = UIBarButtonItem(image: UIImage(named: "imagename"), style: .plain, target: self, action: Selector("action")) // action:#selector(Class.MethodName) for swift 3
self.navigationItem.rightBarButtonItem  = button1

Verifique este Apple Doc. referência


UIBarButtonItem com imagem de botão personalizada usando a moldura do botão

PARA Swift 3.0

    let btn1 = UIButton(type: .custom)
    btn1.setImage(UIImage(named: "imagename"), for: .normal)
    btn1.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
    btn1.addTarget(self, action: #selector(Class.Methodname), for: .touchUpInside)
    let item1 = UIBarButtonItem(customView: btn1)

    let btn2 = UIButton(type: .custom)
    btn2.setImage(UIImage(named: "imagename"), for: .normal)
    btn2.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
    btn2.addTarget(self, action: #selector(Class.MethodName), for: .touchUpInside)
    let item2 = UIBarButtonItem(customView: btn2)  

    self.navigationItem.setRightBarButtonItems([item1,item2], animated: true)

PARA Swift 2.0e mais velhos

let btnName = UIButton()
btnName.setImage(UIImage(named: "imagename"), forState: .Normal)
btnName.frame = CGRectMake(0, 0, 30, 30)
btnName.addTarget(self, action: Selector("action"), forControlEvents: .TouchUpInside)

//.... Set Right/Left Bar Button item
let rightBarButton = UIBarButtonItem()
rightBarButton.customView = btnName
self.navigationItem.rightBarButtonItem = rightBarButton

Ou simplesmente use init (customView :) como

 let rightBarButton = UIBarButtonItem(customView: btnName)
 self.navigationItem.rightBarButtonItem = rightBarButton

Para System UIBarButtonItem

let camera = UIBarButtonItem(barButtonSystemItem: .Camera, target: self, action: Selector("btnOpenCamera"))
self.navigationItem.rightBarButtonItem = camera

Para definir mais de 1 itens, use rightBarButtonItemsou para o lado esquerdoleftBarButtonItems

let btn1 = UIButton()
btn1.setImage(UIImage(named: "img1"), forState: .Normal)
btn1.frame = CGRectMake(0, 0, 30, 30)
btn1.addTarget(self, action: Selector("action1:"), forControlEvents: .TouchUpInside)
let item1 = UIBarButtonItem()
item1.customView = btn1

let btn2 = UIButton()
btn2.setImage(UIImage(named: "img2"), forState: .Normal)
btn2.frame = CGRectMake(0, 0, 30, 30)
btn2.addTarget(self, action: Selector("action2:"), forControlEvents: .TouchUpInside)
let item2 = UIBarButtonItem()
item2.customView = btn2

self.navigationItem.rightBarButtonItems = [item1,item2]

Usando setLeftBarButtonItemousetRightBarButtonItem

let btn1 = UIButton()
btn1.setImage(UIImage(named: "img1"), forState: .Normal)
btn1.frame = CGRectMake(0, 0, 30, 30)
btn1.addTarget(self, action: Selector("action1:"), forControlEvents: .TouchUpInside)
self.navigationItem.setLeftBarButtonItem(UIBarButtonItem(customView: btn1), animated: true);

Para swift> = 2.2, a ação deve ser #selector(Class.MethodName)... por exemplobtnName.addTarget(self, action: #selector(Class.MethodName), forControlEvents: .TouchUpInside)

EI Captain v2.0
fonte
Ótima resposta. Só quero salientar que o método de seleção foi atualizado embora alet camera = UIBarButtonItem(barButtonSystemItem: .Camera, target: self, action: #selector(Class.MethodName))
CodeBender
Descobri que se você deseja que o seu botão inclua também o texto, você deve especificar a parte do CGRect. Existem alguns exemplos flutuando no SO que não especificam isso.
Micah Montoya
obrigado pela sua resposta perfeita. Não é ruim para adicionar uma atualização para rápida 4.
Milad Faridnia
38

É muito mais fácil com Swift 4ouSwift 4.2

dentro do seu ViewDidLoadmétodo, defina seu botão e adicione-o à barra de navegação.

override func viewDidLoad() {
    super.viewDidLoad()

    let logoutBarButtonItem = UIBarButtonItem(title: "Logout", style: .done, target: self, action: #selector(logoutUser))
    self.navigationItem.rightBarButtonItem  = logoutBarButtonItem

}

então você precisa definir a função que você mencionou dentro do parâmetro de ação como abaixo

@objc func logoutUser(){
     print("clicked")
}

Você precisa adicionar o @objcprefixo, pois ele ainda está usando o material herdado (Objetivo C).

Jay Mayu
fonte
17

Basta configurar UIBarButtonItemcom o customView

Por exemplo:

  var leftNavBarButton = UIBarButtonItem(customView:yourButton)
  self.navigationItem.leftBarButtonItem = leftNavBarButton

ou use setFunction:

  self.navigationItem.setLeftBarButtonItem(UIBarButtonItem(customView: yourButton), animated: true);
Leo
fonte
1
Estou votando na sua resposta, pois seu código também funciona, mas o código de Bhavin é uma solução única, então aceitarei a resposta dele. Obrigado por seu companheiro contribuição :)
Rahul Sonvane
11

Acabei de me deparar com esta pergunta e aqui está uma atualização para Swift 3 e iOS 10:

let testUIBarButtonItem = UIBarButtonItem(image: UIImage(named: "test.png"), style: .plain, target: self, action: nil)
self.navigationItem.rightBarButtonItem  = testUIBarButtonItem

Definitivamente, é muito mais rápido do que criar o UIButton com todas as propriedades e, posteriormente, adicionar o customView ao UIBarButtonItem.

E se você deseja alterar a cor da imagem do azul padrão para, por exemplo, branco, você sempre pode alterar a cor da tonalidade:

test.tintColor = UIColor.white()

PS Você obviamente deve alterar o seletor etc. para o seu aplicativo :)

tech4242
fonte
7

No Swift 3.0+, UIBarButtonItemconfigure programaticamente da seguinte maneira:

   override func viewDidLoad() {
        super.viewDidLoad()
        let testUIBarButtonItem = UIBarButtonItem(image: UIImage(named: "test.png"), style: .plain, target: self, action: #selector(self.clickButton))
        self.navigationItem.rightBarButtonItem  = testUIBarButtonItem
    }

   @objc func clickButton(){
            print("button click")
     }
Kushal Shrestha
fonte
3

Definir LeftBarButton com imagem original.

let menuButton = UIBarButtonItem(image: UIImage(named: "imagename").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(classname.functionname))
self.navigationItem.leftBarButtonItem  = menuButton
Sudhi 9135
fonte
2

Tenho o mesmo problema e li as respostas em outro tópico e resolvo de outra maneira semelhante. Não sei qual é mais eficaz. questão semelhante

//play button

@IBAction func startIt(sender: AnyObject) {
    startThrough();
};

//play button

func startThrough() {
    timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("updateTime"), userInfo: nil, repeats: true);

    let pauseButton = UIBarButtonItem(barButtonSystemItem: .Pause, target: self, action: "pauseIt");
    self.toolBarIt.items?.removeLast();
    self.toolBarIt.items?.append( pauseButton );
}

func pauseIt() {
    timer.invalidate();

    let play = UIBarButtonItem(barButtonSystemItem: .Play, target: self, action: "startThrough");
    self.toolBarIt.items?.removeLast();
    self.toolBarIt.items?.append( play );
}
AngelThread
fonte
1

Isso é uma coisa louca da maçã. Quando você diz self.navigationItem.rightBarButtonItem.title, ele diz nada enquanto na GUI mostra Edit ou Save. Fresher gosta de mim levará muito tempo para depurar esse comportamento.

Há um requisito de que o Item mostre Editar na primeira carga e o usuário toque nele. Ele será alterado para Salvar título. Para arquivar isso, fiz como abaixo.

// a visualização carregou dirá Editar título

private func loadRightBarItem() {
    let logoutBarButtonItem = UIBarButtonItem(title: "Edit", style: .done, target: self, action: #selector(handleEditBtn))
    self.navigationItem.rightBarButtonItem  = logoutBarButtonItem
}

// toque em Editar item mudará para Salvar título

@objc private func handleEditBtn() {
    print("clicked on Edit btn")
    let logoutBarButtonItem = UIBarButtonItem(title: "Save", style: .done, target: self, action: #selector(handleSaveBtn))
    self.navigationItem.rightBarButtonItem  = logoutBarButtonItem
    blockEditTable(isBlock: false)
}

// toque em Salvar item exibirá Editar título

@objc private func handleSaveBtn(){
    print("clicked on Save btn")
    let logoutBarButtonItem = UIBarButtonItem(title: "Edit", style: .done, target: self, action: #selector(handleEditBtn))
    self.navigationItem.rightBarButtonItem  = logoutBarButtonItem

    saveInvitation()
    blockEditTable(isBlock: true)

}
codificadores
fonte
1

iOS 11

Configurando um botão personalizado usando restrição:

let buttonWidth = CGFloat(30)
let buttonHeight = CGFloat(30)

let button = UIButton(type: .custom)
button.setImage(UIImage(named: "img name"), for: .normal)
button.addTarget(self, action: #selector(buttonTapped(sender:)), for: .touchUpInside)
button.widthAnchor.constraint(equalToConstant: buttonWidth).isActive = true
button.heightAnchor.constraint(equalToConstant: buttonHeight).isActive = true

self.navigationItem.rightBarButtonItem = UIBarButtonItem.init(customView: button)
Achyut Sagar
fonte
0
func viewDidLoad(){
let homeBtn: UIButton = UIButton(type: UIButtonType.custom)

        homeBtn.setImage(UIImage(named: "Home.png"), for: [])

        homeBtn.addTarget(self, action: #selector(homeAction), for: UIControlEvents.touchUpInside)

        homeBtn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)

        let homeButton = UIBarButtonItem(customView: homeBtn)


        let backBtn: UIButton = UIButton(type: UIButtonType.custom)

        backBtn.setImage(UIImage(named: "back.png"), for: [])

        backBtn.addTarget(self, action: #selector(backAction), for: UIControlEvents.touchUpInside)

        backBtn.frame = CGRect(x: -10, y: 0, width: 30, height: 30)

        let backButton = UIBarButtonItem(customView: backBtn)
        self.navigationItem.setLeftBarButtonItems([backButton,homeButton], animated: true)
}

}
Sai kumar Reddy
fonte