News & Events
Tutorial: Criando meu app step-by-step – Botões de Hardware – Parte IX
- 15 de dezembro de 2014
- Posted by: Adriano Santos
- Category: Notícias XE7 [Tutorial]
A parte IX de nosso Tutorial: Criando meu app step-by-step traz a você todos os detalhes para o uso de dois importantes botões de hardware no Android, os botões Back e Menu. Esses botões são comuns e aparecem em todos os aparelhos munidos de sistema operacional Android, sejam botões físicos ou virtuais. O botão Home também existe e é comum, mas varia um pouco o uso em cada aparelho. O aparelho que usamos para testar nossas aplicações por exemplo, um Samsung Win Duos, possui todos esses botões em formato físico, comum em aparelhos Samsung. Nosso Tablet Multilaser por outro lado, possui apenas botões virtuais.
Como devem ter notado, essa fase de nosso tutorial será mais light, mas não menos importante. Além de vermos como fazer uso dos botões Back e Menu em nosso aplicativo, aprenderemos dicas importantes relacionadas ao controle da aplicação usando tais botões.
Para relembrarmos o que vimos na edição passada, veja abaixo em forma de tópicos. Nós vimos basicamente o uso de ArrayDML e algumas dicas para liberação de memória.
- Comandos ArrayDML para rápida inserção no banco;
- Ajustes na liberação de memória de objetos FORM;
E como mencionado, veremos aqui:
- Como fazer uso dos botões Back e Menu?
Requisitos
- Leitura: Artigos de I a VIII desse tutorial.
Botões de Hardware
Antes de codificarmos nosso sistema, vamos entender qual a ideia de usar os botões de hardware, em quais momentos vamos utiliza-los e onde detectar o seu pressionamento. Se recapitularmos nosso app, vamos lembrar que temos algumas telas que são acessadas via Menu Principal. Algumas delas possuem navegação, ou seja, botões virtuais Próximo e Anterior. É aqui que entra o botão Back. Queremos que ao tocar no botão, uma aba (TabControl) retorne. Já o botão Menu, vamos usa-lo em dois momentos:
- Quando o usuário desejar abrir o Menu Principal;
- E quando houverem menus Pop-up;
Agora, onde detectar que o usuário tocou nos botões? Os botões de hardware no Android precisam ser programados manualmente, praticamente hardcoded, isso porque eles não tem como saber em qual tela estamos em nosso app e muito menos para onde vamos. Outra coisa importante é que temos um Form Principal que praticamente comanda o app inteiro. Lembre-se da primeira parte do tutorial quando montamos a arquitetura de navegação. Temos um TLayout no form principal e outro TLayout em cada nova janela, e ao abrir uma nova janela, nós adicionamos o Layout do alvo ao Layout do form principal. (Figura 1)
Figura 1. Exemplo de tela com menu
Em outras palavras, é como se adicionássemos os demais formulários ao formulário principal, portanto o comando central é o Form Principal. Se colocarmos algum código nos evento OnKeyUp do formulário alvo, esse não será acionado, ao contrário, o evento acionado será o OnKeyUp do form principal. Por isso é nele que programaremos tudo. Selecione o evento OnKeyUp e clique duas vezes nele para iniciarmos a programação.
A primeira providência é declararmos uma nova variável a esse evento.
- FService do tipo IFMXVirtualKeyboardService. Essa variável será responsável por verificar se o teclado está visível, pois se estiver, ignoramos os botões Back e Menu.
O escopo do nosso evento pode ser visto na Listagem 1.
var FService : IFMXVirtualKeyboardService; begin end;
Listagem 1. Início da codificação do OnKeyUp
Agora vamos implementar todo o mecanismo de detecção dos botões na Listagem 1. Continuemos a codificação recebendo o estado do teclado na variável FService. A primeira linha do evento OnKeyUp segue como abaixo:
#Dica: Para termos acesso aos TPlatformServices e a Interface IFMXVirtualKeyboardService, declare as units FMX.VirtualKeyboard, FMX.Platform, FMX.Helpers.Android, FMX.Platform.Android, no uses do form.
{Recebe o estado do teclado virtual} TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FService));
Em seguida começamos toda a brincadeira. Para o botão Back basta checarmos o estado da variável Key presente no evento. Perceba que a assinatura do evento OnKeyUp possui um Sender, um Key e um KeyChar. Testaremos Key para verificar qual tecla (ou botão) foi pressionada. Podemos usar apenas:
if Key - vkHardwareBAck then //Codificação
Veja como é simples. Para o botão menu, basta testarmos se o Key é igual a vkMenu. O código-fonte da Listagem 2 refere-se ao código completo do nosso mecanismo, então vamos entender uma por uma das chamadas.
procedure TfrmMain.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState); var FService : IFMXVirtualKeyboardService; begin {Recebe o estado do teclado virtual} TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FService)); {Se o botão back pressionado e o teclado virtual ativo, não faz nada} if Key = vkHardwareBack then begin if (FService <> nil) and (TVirtualKeyboardState.Visible in FService.VirtualKeyBoardState) then begin //Reservado, não faz nada end else begin {Verifica qual formulário está ativo e então chama o método Voltar} {Se NÃO estiver com a listagem de pedidos aberta} {$Region 'Menu'} if MultiView1.IsShowed then begin MultiView1.HideMaster; Key := 0; end {$EndRegion} {$Region 'Titulos'} else if (FTitulos.lytTitulos.Visible) and not (FTitulos.tabctrlTitulos.ActiveTab = FTitulos.tbitemLisTitulos) then FTitulos.PressionouVoltar else if (FTitulos.lytTitulos.Visible) and (FTitulos.tabctrlTitulos.ActiveTab = FTitulos.tbitemLisTitulos) then begin MessageDlg('Deseja sair do aplicativo?', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0, procedure (const AResult: TModalResult) begin if AResult = mrYes then begin {$IFDEF ANDROID} MainActivity.finish; {$ELSE} exit; {$ENDIF} end; end ); end {$EndRegion} {$Region 'Preferências'} else if (Assigned(FPreferencias)) then begin MessageDlg('Deseja sair do aplicativo?', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0, procedure (const AResult: TModalResult) begin if AResult = mrYes then begin {$IFDEF ANDROID} MainActivity.finish; {$ELSE} exit; {$ENDIF} end; end ); end; {$EndRegion} Key := 0; end; end {Botão Menu do Android} else if Key = vkMenu then begin if (FService <> nil) and (TVirtualKeyboardState.Visible in FService.VirtualKeyBoardState) then begin //Reservado, não faz nada end {O menu está sendo mostrado, apenas fecha o menu} else begin if MultiView1.IsShowed then HideBackground {Verifica se o Pedidos está sendo mostrado e não está na lista de pedidos, para então abrir o menu} else if (FTitulos.lytTitulos.Visible) then FTitulos.PressionouMenu; Key := 0; end; end; end;
Listagem 2. Código Completo
O código não contempla todas as situações, a ideia é somente dar o caminho das pedras. Na primeira parte de nosso código referente ao botão Back, nós verificamos se o menu principal está aberto. Caso ele esteja, nós verificamos se o menu principal está aberto, por isso a instrução MuiltiView1.HideMaster. Ela fecha o menu. Caso contrário, passamos a verificar qual janela está aberta. Fazemos isso usando as variáveis de cada formulário, ex. Se o layout principal de FTitulos estiver visível, significa que a janela de Títulos está aberta no momento. Para que o menu back funcione, testamos também se estamos na aba tbitemListTitulos, nesse caso chamamos o método PressionouVoltar do formulário Titulos. Esse método deverá ser criado como a seguir:
procedure TfrmTitulos.PressionouVoltar; begin if tabctrlTitulos.ActiveTab = tbitemDetalhes then tabctrlTitulos.Previous(); end;
Perceba como é simples. Após verificar que o menu não está aberto e que não estamos na aba principal de Titulos, nós chamamos o método PressionouVoltar da tela alvo e deixamos que o método decida o que fazer. Nesse caso verificamos se a aba Detalhes está aberta, caso esteja, então voltamos uma aba.
Dessa maneira faremos em todas as janelas, criando um método PressionouVoltar e codificando o que queremos que aconteça, tela a tela. A mesma codificação, fazemos para a tela de preferências de sistema, a única diferença é que testamos se a janela está criada usando um Assigned na variável do form, isso porque preferências é criada e destruída sempre.
Retornando ao formulário principal, o final da codificação diz respeito ao botão menu. Nesse caso testamos se o Key é igual a vkMenu, para então fazermos os devidos testes. Em nosso exemplo, temos apenas um teste que é referente a janela Titulos. Caso ela esteja visível, então chamamos o método PressionouMenu do próprio FTitulos, ou seja, mais uma vez o controle é dado ao formulário. O método PressionouMenu deverá ser criado como a seguir:
procedure TfrmTitulos.PressionouMenu; begin if (tabctrlTitulos.ActiveTab = tbitemLisTitulos) then frmMain.MultiView1.ShowMaster else if (tabctrlTitulos.ActiveTab = tbitemLisTitulos) and (DM.qryTitulos.State in dsEditModes) then imgFotoClick(imgFoto); end;
Como mencionado, mais uma vez o formulário tem o controle da situação. Aqui nesse caso estamos verificando qual aba está aberta. Se a aba visível for a principal, abrimos o menu principal. Se Detalhes for a aba visível e estivermos em modo de Edição, descemos o menu pop-up para que o usuário troque a foto do título.
Basicamente é só isso que precisamos fazer. Parece complicado, mas na verdade somente é trabalhoso e precisamos ter muita atenção na codificação. A última coisa a explicar aqui é sobre a linha Key := 0 vista em vários lugares no código da tela principal, OnKeyUp. Isso é necessário, pois se o Key não receber zero a após o pressionamento, o evento continuará a executar linha a linha e então teremos problemas.
Fica agora ao seu gosto, codificar o restante das telas usando como base o código explicado acima.
Conclusão
O usuário Android está bastante acostumado a usar os botões de hardware para voltar telas ou abrir menus. Por isso é importantíssimo que codifiquemos cada botão para que a navegação do app fique mais transparente. Em iOS isso não é possível, isso porque existem poucos botões e o que exitem estão destinados a funções específicas. A Apple não permite que você utilize um botão de hardware para alguma função diferente da que ele foi criado, exemplo. Um botão para aumentar volume, apenas aumenta volume e nada mais. Recentemente a Apple liberou o uso do botão Aumentar Volume para que seja usado em aplicativos de foto, nada mais.
Outro detalhe não mencionado na codificação foi a instrução MainActivity.finish; Essa instrução finaliza totalmente a aplicação Android, como se fosse um Application.Terminate em aplicativos Desktop. Isso é de muita importância, só com essa instrução garantimos que o app será totalmente fechado e que todas as variáveis, forms, etc sejam liberados de memória. Em iOS isso não é necessário.
Caso tenha interesse em ver mais informações sobre outros botões, verifique a DocWiki da Embarcadero.
#GoToDelphi
Author: Adriano Santos
2 Comentários
Comments are closed.
[…] Head over and check out the full blog post plus code snippet for handling the device hardware button… […]
[…] Leitura: Tutorial: Criando meu app step-by-step Parte IX […]