fix(android): the back key folds the keyboard before anything else

It was our own handler. The web view is not a field the system knows, so
it does not intercept the key for us - it arrives here, and we consumed
it in every case: the vault locked, or the list came back, while the
keyboard stayed up with no way left to close it.

hideSoftInputFromWindow answers whether there was anything to fold, which
is the synchronous signal needed to decide. Something folded, key eaten;
nothing folded, the key keeps its usual meaning.

Measured on the device, before and after: mInputShown stayed true, it now
goes false and the application stays in front. A second press locks, as
before.
This commit is contained in:
r-zakarya
2026-08-21 12:48:29 +01:00
parent 90ea09a718
commit 8f8a8ec3f4
2 changed files with 52 additions and 1 deletions
+42 -1
View File
@@ -29,13 +29,26 @@ procedure SecureScreen;
/// l'impression que l'application occupe l'ecran plutot que d'y etre posee.
procedure TintSystemBars(ATop, ABottom: TAlphaColor);
/// Replie le clavier, et dit s'il etait bien deplie.
///
/// LA REPONSE COMPTE AUTANT QUE L'ACTION. La touche retour arrive chez nous
/// avant le clavier - la vue web n'est pas un champ que le systeme connait -
/// et notre gestionnaire la consommait toujours, verrouillant le coffre ou
/// remontant a la liste pendant que le clavier restait deplie, sans plus aucun
/// moyen de le refermer. Savoir s'il y avait quelque chose a replier permet de
/// rendre a la touche son premier sens et de ne consommer que dans ce cas.
///
/// A appeler depuis le thread d'interface, et sans differer : celui qui appelle
/// decide de la suite d'apres la reponse.
function HideSoftKeyboard: Boolean;
implementation
{$IF DEFINED(ANDROID)}
uses
// System.SysUtils : sans elle, TAndroidHelper.GetJActivity reste un appel
// non expanse et le compilateur le signale a chaque usage.
System.SysUtils, Androidapi.Helpers, Androidapi.JNI.App,
System.SysUtils, Androidapi.JNI.JavaTypes, Androidapi.Helpers, Androidapi.JNI.App,
Androidapi.JNI.GraphicsContentViewText, FMX.Helpers.Android;
procedure SecureScreen;
@@ -85,4 +98,32 @@ begin
end;
{$ENDIF}
{$IF DEFINED(ANDROID)}
function HideSoftKeyboard: Boolean;
var
LService: JObject;
LView: JView;
begin
Result := False;
try
LView := TAndroidHelper.Activity.getWindow.getDecorView;
if LView = nil then Exit;
LService := TAndroidHelper.Context.getSystemService(
TJContext.JavaClass.INPUT_METHOD_SERVICE);
if LService = nil then Exit;
// Rend False si rien n'etait deplie : c'est notre reponse.
Result := TJInputMethodManager.Wrap(LService)
.hideSoftInputFromWindow(LView.getWindowToken, 0);
except
// Un clavier qui ne se replie pas ne doit pas emporter la touche retour.
Result := False;
end;
end;
{$ELSE}
function HideSoftKeyboard: Boolean;
begin
Result := False;
end;
{$ENDIF}
end.
+10
View File
@@ -379,6 +379,16 @@ procedure TForm8.OnHardwareBack(Sender: TObject; var Key: Word;
begin
if Key <> vkHardwareBack then Exit;
if not FLayWeb.Visible then Exit;
// LE CLAVIER D'ABORD. Quand il est deplie, cette touche est le bouton qui le
// replie - c'est tout ce qu'elle veut dire. La vue web n'etant pas un champ
// que le systeme connait, il ne l'intercepte pas pour nous : on verrouillait
// le coffre pendant que le clavier restait en place, sans plus aucun moyen de
// le refermer.
if HideSoftKeyboard then
begin
Key := 0;
Exit;
end;
// C'est la PAGE qui sait ce qu'elle affiche - Delphi ne le devine pas. Elle
// le declare a chaque changement de vue (cmd://state).
if FWebView = 'detail' then