3

Can you help me how to hide (and again show) soft keyboard while TEdit is in focus?

pudnivec74
  • 770
  • 1
  • 7
  • 22
  • Tried `InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);?` – MysticMagicϡ Dec 10 '14 at 13:22
  • See this: [Close/hide the Android Soft Keyboard][1] [1]: http://stackoverflow.com/questions/1109022/close-hide-the-android-soft-keyboard – Hamidreza Samadi Dec 10 '14 at 13:36
  • I need solution for DELPHI – pudnivec74 Dec 10 '14 at 15:22

6 Answers6

11

I have a solution:

  1. In the .dpr set VKAutoShowMode to Never

    begin
      Application.Initialize;
      VKAutoShowMode := TVKAutoShowMode.Never;
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end. 
    
  2. Show soft keyboard on the form (for example on TEdit.OnEnter event):

    var
      FService: IFMXVirtualKeyboardService;
    begin
      TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FService));
      if (FService <> nil) then
      begin
        FService.ShowVirtualKeyboard(Edit1);
        Edit1.SetFocus;
      end;
    
  3. Hide soft keyboard on the form (Edit1 will be still focused with hidden soft keyboard):

    var
      FService: IFMXVirtualKeyboardService;
    begin
      TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FService));
      if (FService <> nil) then
      begin
        FService.HideVirtualKeyboard;
        Edit1.SetFocus;
      end;
    
Kromster
  • 6,665
  • 7
  • 55
  • 98
pudnivec74
  • 770
  • 1
  • 7
  • 22
  • Thanks , this information is good and works to me on Delphi XE7 with android. But, I have one question, is this the easy way ? – Cletrix Mar 23 '15 at 14:14
  • Currently yes. Embarcadero working on correcting mistakes in this matter. Repair should be released in the next version of Delphi. – pudnivec74 Mar 23 '15 at 14:21
  • Doesn't work with Delphi 10.2 (Tokyo) and Android 6. Keyboard stays visible – ArieKanarie Jan 15 '18 at 13:06
4

The solution is very easy and straight forward:

Wrap the original IFMXVirtualKeyboardService with your own and check if the control should have a virtual keyboard or not.

Here is a complete wrapper for that and not limited to Android

unit Common.FMX.VirtualKeyboardService;

interface

uses
  System.Classes,
  System.Generics.Collections,
  FMX.Types,
  FMX.VirtualKeyboard;

type
  TVirtualKeyboardService = class( TComponent, IFMXVirtualKeyboardService )
  private
    FObjects: TList<TFmxObject>;
    FOriginalService: IFMXVirtualKeyboardService;
    constructor Create( AOwner: TComponent );
    class constructor Create;
  protected
    function GetVirtualKeyboardState: TVirtualKeyboardStates;
    function HideVirtualKeyboard: Boolean;
    procedure SetTransientState( Value: Boolean );
    function ShowVirtualKeyboard( const AControl: TFmxObject ): Boolean;
    procedure Notification( AComponent: TComponent; Operation: TOperation ); override;
  public
    class function Current: TVirtualKeyboardService;
    destructor Destroy; override;

    procedure AddOverrideObject( AObject: TFmxObject );
    procedure RemoveOverrideObject( AObject: TFmxObject );
    function IsOverriddenObject( AObject: TFmxObject ): Boolean;
  private
    class var _current: TVirtualKeyboardService;
  end;

implementation

uses
  FMX.Forms,
  FMX.Platform,
  System.SysUtils;

{ TVirtualKeyboardService }

constructor TVirtualKeyboardService.Create( AOwner: TComponent );
begin
  inherited Create( AOwner );

  FObjects := TList<TFmxObject>.Create;

  if TPlatformServices.Current.SupportsPlatformService( IFMXVirtualKeyboardService, FOriginalService ) then
  begin
    TPlatformServices.Current.RemovePlatformService( IFMXVirtualKeyboardService );
    TPlatformServices.Current.AddPlatformService( IFMXVirtualKeyboardService, Self );
  end;
end;

procedure TVirtualKeyboardService.AddOverrideObject( AObject: TFmxObject );
begin
  if Supports( AObject, IVirtualKeyboardControl ) and not FObjects.Contains( AObject ) then
  begin
    FObjects.Add( AObject );
    Self.FreeNotification( AObject );
  end;
end;

class constructor TVirtualKeyboardService.Create;
begin
  TVirtualKeyboardService._current := TVirtualKeyboardService.Create( Application );
end;

class function TVirtualKeyboardService.Current: TVirtualKeyboardService;
begin
  Result := TVirtualKeyboardService._current;
end;

destructor TVirtualKeyboardService.Destroy;
begin
  if Assigned( FOriginalService ) then
  begin
    TPlatformServices.Current.RemovePlatformService( IFMXVirtualKeyboardService );
    TPlatformServices.Current.AddPlatformService( IFMXVirtualKeyboardService, FOriginalService );
  end;
  FObjects.Free;
  inherited;
end;

function TVirtualKeyboardService.GetVirtualKeyboardState: TVirtualKeyboardStates;
begin
  Result := FOriginalService.VirtualKeyboardState;
end;

function TVirtualKeyboardService.HideVirtualKeyboard: Boolean;
begin
  Result := FOriginalService.HideVirtualKeyboard;
end;

function TVirtualKeyboardService.IsOverriddenObject( AObject: TFmxObject ): Boolean;
begin
  Result := FObjects.Contains( AObject );
end;

procedure TVirtualKeyboardService.Notification( AComponent: TComponent; Operation: TOperation );
begin
  inherited;
  if ( Operation = opRemove ) and ( AComponent is TFmxObject ) then
  begin
    RemoveOverrideObject( AComponent as TFmxObject );
  end;
end;

procedure TVirtualKeyboardService.RemoveOverrideObject( AObject: TFmxObject );
begin
  if FObjects.Contains( AObject ) then
  begin
    FObjects.Remove( AObject );
    Self.RemoveFreeNotification( AObject );
  end;
end;

procedure TVirtualKeyboardService.SetTransientState( Value: Boolean );
begin
  FOriginalService.SetTransientState( Value );
end;

function TVirtualKeyboardService.ShowVirtualKeyboard( const AControl: TFmxObject ): Boolean;
begin
  if IsOverriddenObject( AControl ) then
    begin
      HideVirtualKeyboard;
      Result := False;
    end
  else
    Result := FOriginalService.ShowVirtualKeyboard( AControl );
end;

end.

If you want to disable the virtual keyboard for your control, just call

uses
  Common.FMX.VirtualKeyboardService;

procedure TForm1.AfterConstruction;
begin
  inherited;
  TVirtualKeyboardService.AddOverrideObject( Edit1 );
end;

Thats it.

Sir Rufo
  • 16,671
  • 2
  • 33
  • 66
3

Try to use variable VKAutoShowMode in FMX.Types

2

Just add the following lines of code to the OnClick event of the control. It seems to work fine.

edit1.resetfocus; edit1.setfocus;

Loc Nguyen
  • 21
  • 2
0

Just found a really easy solution.

In my OnKeyDown event I am checking for vkEnter and executing some code. I want to keyboard to close up as I'm done.

Just set my TEdit to not Enabled and back again, ie:

procedure TfrmMain.dtBarCodeKeyDown(Sender: TObject; var Key: Word;
  var KeyChar: Char; Shift: TShiftState);
begin
  if Key = vkReturn then
    begin
      dtBarCode.Enabled := false; //kill the keyboard
      try
        LoadBarCode;
      finally
        dtBarCode.Enabled := true;
      end;
    end;
end;

If the user clicks into the text field again, the keyboard comes back.

Tested on Android

Maya
  • 273
  • 5
  • 10
-2

Try with below code:

InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
Pratik Dasa
  • 7,103
  • 4
  • 26
  • 43