如何在焦点为TEdit时隐藏(并再次显示)软键盘 DELPHI XE7

4

你能帮我解决在TEdit获得焦点时如何隐藏软键盘(并再次显示)的问题吗?


尝试过这段代码吗?InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0); - MysticMagicϡ
请参见:关闭/隐藏Android软键盘 - Hamidreza Samadi
我需要DELPHI的解决方案。 - pudnivec74
6个回答

12

我有一个解决方案:

  1. .dpr文件中将VKAutoShowMode设置为Never

begin
  Application.Initialize;
  VKAutoShowMode := TVKAutoShowMode.Never;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end. 
  • 在表单上显示软键盘 (例如在TEdit.OnEnter事件上):

  • var
      FService: IFMXVirtualKeyboardService;
    begin
      TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FService));
      if (FService <> nil) then
      begin
        FService.ShowVirtualKeyboard(Edit1);
        Edit1.SetFocus;
      end;
    
  • 隐藏软键盘在表单中(Edit1仍然会聚焦,但软键盘已隐藏)

    var
      FService: IFMXVirtualKeyboardService;
    begin
      TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FService));
      if (FService <> nil) then
      begin
        FService.HideVirtualKeyboard;
        Edit1.SetFocus;
      end;
    

  • 谢谢,这个信息对我在 Delphi XE7 上使用 Android 很有帮助。但是,我有一个问题,这是最简单的方法吗? - Cletrix
    目前是这样的。Embarcadero正在努力纠正这个问题。修复应该会在下一个Delphi版本中发布。 - pudnivec74
    不兼容Delphi 10.2(Tokyo)和Android 6。键盘仍然可见。 - ArieKanarie

    5
    解决方案很简单和直接:
    用你自己的IFMXVirtualKeyboardService来封装原始的服务,并检查控件是否需要虚拟键盘。
    这是一个完整的包装器,不仅限于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.
    

    如果您想禁用控件的虚拟键盘,只需调用以下方法:
    uses
      Common.FMX.VirtualKeyboardService;
    
    procedure TForm1.AfterConstruction;
    begin
      inherited;
      TVirtualKeyboardService.AddOverrideObject( Edit1 );
    end;
    

    这就是它。


    3
    尝试在FMX.Types中使用变量VKAutoShowMode。

    2

    只需将以下代码添加到控件的OnClick事件中即可。看起来运行得很好。

    edit1.resetfocus; edit1.setfocus;


    我在Android和Windows FMX上尝试了TSpinBox,它大部分时间都能正常工作。 - Freddie Bell

    0

    刚刚找到了一个非常简单的解决方案。

    在我的 OnKeyDown 事件中,我检查 vkEnter 并执行一些代码。我想让键盘关闭,因为我已经完成了。

    只需将我的 TEdit 设置为不可用,然后再设置回来即可:

    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;
    

    如果用户再次点击文本字段,则键盘会重新出现。
    在Android上测试过。

    -2

    请尝试以下代码:

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

    1
    我需要DELPHI的解决方案。 - pudnivec74

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接