Pregunta

How can I make my Android app react to the back-button?

Is there something as high-level VCL's TApplicationEvents to handle it, or do I need to dive deep into low-level Android-specific stuff here?

Right now, most of the demo applications have an on-screen back button to go back to a previous screen. Pressing the psysical button always seems to quit the app, and in some situations it results in an access violation.

¿Fue útil?

Solución

In the form's OnKey... events, the Key parameter is vkHardwareBack on Android. For example:

uses
  FMX.Platform, FMX.VirtualKeyboard;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);
var
  FService : IFMXVirtualKeyboardService;
begin
  if Key = vkHardwareBack then
  begin
    TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FService));
    if (FService <> nil) and (vksVisible in FService.VirtualKeyBoardState) then
    begin
      // Back button pressed, keyboard visible, so do nothing...
    end else
    begin
      // Back button pressed, keyboard not visible or not supported on this platform, lets exit the app...
      if MessageDlg('Exit Application?', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbOK, TMsgDlgBtn.mbCancel], -1) = mrOK then
      begin
        // Exit application here...
      end else
      begin
        // They changed their mind, so ignore the Back button press...
        Key := 0;
      end;
    end;
  end
  ...
end;

Otros consejos

For future reference to anyone trying to make sense of this..

if Key = vkHardwareBack then
    begin
      // your code here
      key := 0;
end;

The key := 0; is the secret to stop the app from closing..

This goes in the forms OnKeyUp event

Here is an updated code for Remy's answer (works with Seattle):

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);
var
  FService : IFMXVirtualKeyboardService;
begin
  if Key = vkHardwareBack then
  begin
    TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FService));
    if (FService <> nil) and (TVirtualKeyboardState.Visible in FService.VirtualKeyBoardState) then
    begin
      // Back button pressed, keyboard visible, so do nothing...
    end else
    begin
      Key := 0;
      // Back button pressed, keyboard not visible or not supported on this platform, lets exit the app...
      MessageDlg('Exit Application?', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbOK, TMsgDlgBtn.mbCancel], -1, OnCloseDialog);
    end;
  end;
end;

procedure TForm1.OnCloseDialog(Sender: TObject; const AResult: TModalResult);
begin
  if AResult = mrOK then
    Close;
end;

Going back to the previous screen depends on your application design.

  • If you used TTabControl for displaying pages, you can navigate to the previous TTabItem.

  • If you used TForms for displaying pages, you must use Close() procedure for closing the current form and going back to the previous screen.

Try this:

uses FMX.Platform,FMX.VirtualKeyboard,FMX.Helpers.Android;

procedure THeaderFooterForm.FormKeyUp(Sender: TObject; var Key: Word;
  var KeyChar: Char; Shift: TShiftState);

var FService : IFMXVirtualKeyboardService; 
begin
  if Key = vkHardwareBack then
    begin
      TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FService));
      if (FService <> nil) and (vksVisible in FService.VirtualKeyBoardState) then
        begin
          // Back button pressed, keyboard visible, so do nothing...
        end
      else
        begin
          if MessageDlg('Exit Application?', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbOK, TMsgDlgBtn.mbCancel], -1) = mrOK then
            begin
            // Exit application here...
              SharedActivity.Finish;
            end;
        end;
     end
  else
    // Menu button pressed
    if Key = sgiUpRightLong then
      begin
        showmessage('Menu button pressed');
      end;
end;

The Card View Wizard 1.0 available from GetIt Package Manager (https://getitnow.embarcadero.com/card-view-wizard/) has this code (I only changed the plain "// do nothing comment" there to be more descriptive) for exiting the app only when a set of startup card sequence is still or back on the 1st card, else navigate to previous card:

procedure TMainForm.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char;
  Shift: TShiftState);
var
  FService : IFMXVirtualKeyboardService;
begin
  if Key = vkHardwareBack then
  begin
    TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FService));
    if (FService <> nil) and (TVirtualKeyboardState.Visible in FService.VirtualKeyBoardState) then
      begin
        // Back button pressed, keyboard visible, so do nothing...
      end
    else
      begin
        if WizardTabControl.ActiveTab <> TabItem1 then
          begin
            WizardTabControl.SetActiveTabWithTransitionAsync(WizardTabControl.Tabs[WizardTabControl.TabIndex-1],TTabTransition.Slide,TTabTransitionDirection.Reversed,nil);
            Key := 0;
          end;
      end;
  end
end;

Of course as other answers show you could also prompt the user in case they accidentally tried to exit the application, to not proceed.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top