How to hide (and again show) soft keyboard while TEdit is in focus DELPHI XE7

17.8k Views Asked by At

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

6

There are 6 best solutions below

3
On BEST ANSWER

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;
    
1
On

Try with below code:

InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
0
On

Try to use variable VKAutoShowMode in FMX.Types

0
On

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.

0
On

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

1
On

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

edit1.resetfocus; edit1.setfocus;