2

I have found many references to this problem, but I have not yet found a solution.

I use the following code to hide the virtual keyboard, but it does not work.

FService: IFMXVirtualKeyboardService;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
  TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FService));
  if FService = nil then ShowMessage('xxxxx');
end;
.....
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);
begin
  //ShowMessage(IntToStr(Key) + '~' + KeyChar + '~');
  //Application.ProcessMessages;
  if (Key = vkHardwareBack) then
  begin
    // this code is executed
    Application.Terminate;
    Key := 0;
  end
  else
  if Key in [vkRETURN, vkACCEPT] then begin
    // this code never executed
    if (FService <> nil) then begin // FService isn't nil
      FService.HideVirtualKeyboard;
    end;
  end;
end;

When "Accept" or "Enter" is pressed, the value of Key is always zero, so the keyboard code is not executed. Why?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
JimPapas
  • 715
  • 2
  • 12
  • 27

4 Answers4

1

This is code from my Android apps that has been working in 10.0 up to 10.3.1

procedure TfrmAppMain.FormKeyDown(Sender: TObject; var Key: Word;
  var KeyChar: Char; Shift: TShiftState);
begin
  {$ifdef ANDROID}
  // make enter like tab which shifts focus to the next control
  // and may cause the keyboard to disappear and reappear in quick succession
  // depending on the .killfocusbyreturn property of the current control
  if Key = vkReturn then
  begin
    Key := vkTab;
    KeyDown(Key, KeyChar, Shift);
  end;
  {$endif}
end;
Freddie Bell
  • 2,186
  • 24
  • 43
  • Yes, the killfocusbyreturn property does the job! allthout vkTab doesn't move focus to the next control – JimPapas Mar 20 '19 at 20:08
0

I'm currently working in 10.1 Berlin, so I think it should work, and I call a procedure

Keyboard: IFMXVirtualKeyboardService;

procedure CallForKeyboard(open: Boolean; input: TFmxObject);
begin
if open then
   begin
       Keyboard.ShowVirtualKeyboard(input);
   end
else
begin
   if TVirtualKeyBoardState.Visible in Keyboard.GetVirtualKeyBoardState then
      Keyboard.HideVirtualKeyboard;
   end;
end;

When I want to OPEN the Virtual Keyboard I Call:

CallForKeyboard(true, sender)

if I want to close the Keyboard I call:

CallForKeyboard(false,nil)
Relinkvent
  • 111
  • 1
  • 3
  • 11
  • I don't need a function to open the keyboard because it autoopens when i tap in the edit's area. For the closing already i use the HideVirtualKeyboard procedure. But the problem is to intercept the ENTER/ACCEPT key – JimPapas Mar 20 '19 at 11:49
  • @JimPapas Have you tried to only have else if (Key = vkReturn) then ... ? – Relinkvent Mar 20 '19 at 12:00
  • yes. It was my first approach but after its failing i added the "vkACCEPT" because the keyboard has a check key instead of "RETURN". Notice that this code was working in D10.1 – JimPapas Mar 20 '19 at 12:25
0

Use the FormkeyUp event handler:

procedure TfrmAppMain.FormKeyUp(Sender: TObject; var Key: Word;
  var KeyChar: Char; Shift: TShiftState);
begin
  {$ifdef ANDROID}
  if Key = vkHardwareBack then
  begin
    if FKeyBoardShown or KeyBoardVisible then // it lies
    begin
      // allow default behaviour - which hides the keyboard
      // note: keyboardvisible also returns true on readonly fields
      if (Self.Focused is TEdit) and TEdit(Self.Focused).ReadOnly then
      begin
        FToast.MakeToast('Press again to exit');
        FBackPressed := True;
      end;
    end
    else
    begin
      Key := 0; // NOTE: intercept default behaviour (which is to close the app)
      if FBackPressed then
      begin
        SaveDataandClose; // which then calls Self.Close later
      end
      else
      begin
        FToast.MakeToast('Press again to exit');
        FBackPressed := True;
      end
    end;
  end;
  {$endif}
end;

This code also emulates the "press again to exit" functionality you see in many Android Apps. To make that work properly, you also have to do this:

procedure TfrmAppMain.FormTouch(Sender: TObject; const Touches: TTouches;
  const Action: TTouchAction);
begin
  FBackPressed := False; // as soon as they touch the form, the exit flag is reset
end;
Freddie Bell
  • 2,186
  • 24
  • 43
  • My goal is to intercept the RETURN or ACCEPT key, not just only for closing the keyboard, eg. the user writes a number or a text and at the end presses the return/accept key to inform the app that he/she finished and wants to close the keyboard to continue with other editing. – JimPapas Mar 20 '19 at 11:45
  • On each relevant control set the `.killfocusbyreturn` property. Then see my other answer below. – Freddie Bell Mar 20 '19 at 17:43
0

Just use this for Delphi Alexandria, FMX:
Keyboard: IFMXVirtualKeyboardService if TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService,Keyboard) then
begin
if TVirtualKeyBoardState.Visible in Keyboard.GetVirtualKeyBoardState then
Keyboard.HideVirtualKeyboard;
end;
sorry guys i have no idea how to format this. but just copy past it and format it yourself.