VirtualKeyboard not Show when focus Edit fields in

2019-03-05 03:52发布

问题:

I have a Firemonkey multi device project in Delphi 10 Seattle where the user can get a screen at the start of the app. Here the user needs to fill in 2 fields. But when I click on the edit fields the Virtual Keyboard isn't shown. If I skip this screen at start and call it later then the Virtual Keyboard is shown. This is done in the same way too.

I found sort of a solution: When i click on the edit fields i call show VirtualKeyboard myself. The only problem is that the cursor isn't shown in the edit field.

Is there a way to place the cursor myself? Or does anyone know how to solve the Virtual Keyboard not showing problem in an other way?

Problem is on both Android and iOS

In the code below you can see the initial form create. The problem is when in ConnectFromProfile method the actCreateNewProfileExecute is called. There it will call a new form. In that form(TfrmProfile) the virtual keyboard isn't shown. I also call this form with another action and then it works fine.

procedure TfrmNocoreDKS.FormCreate(Sender: TObject);
begin
  Inherited;
  System.SysUtils.FormatSettings.ShortDateFormat := 'dd/mm/yyyy';
  CheckPhone;
  ConnectfromProfile;
  if not Assigned(fProfileAction) then
    ConnectDatabase
  Else
    lstDocuments.Enabled := False;

{$IFDEF ANDROID}
  ChangeComboBoxStyle;
{$ENDIF}
end;

procedure TfrmNocoreDKS.ConnectfromProfile;
begin
  fdmProfileConnection := TdmConnection.Create(nil);
  fdmProfileConnection.OpenProfileDb;
  fdmProfileConnection.LoadProfiles;

  if fdmProfileConnection.Profiles.Count = 0 then
  begin // Createdefault Profile
    fProfileAction := actCreateNewProfileExecute;
  end
  else if fdmProfileConnection.Profiles.Count = 1 then
  begin // one profile load connection;
    fProfileAction := nil;
    fCurrentProfile := fdmProfileConnection.Profiles.Items[0];
  end
  else
  begin // multiple profiles choose connection;
    fProfileAction := SelectProfileOnStartUp;
  end;
end;

procedure TfrmNocoreDKS.FormShow(Sender: TObject);
begin
  if Assigned(fProfileAction) then
    fProfileAction(Self);
end;

procedure TfrmNocoreDKS.actCreateNewProfileExecute(Sender: TObject);
var
  profilename, databasename, pathname: string;
  prf: TfrmProfile;
begin
  prf := TfrmProfile.Create(nil);
  prf.Data := fdmProfileConnection.Profiles;
  prf.ShowModal(
    procedure(ModalResult: TModalResult)
    begin
      if ModalResult = mrOk then
      begin
        profilename := prf.edtProfilename.Text;
        databasename := prf.edtDatabaseName.Text;

{$IFDEF IOS}
        pathname := System.IOUtils.TPath.GetDocumentsPath;
{$ENDIF}
{$IFDEF ANDROID}
        pathname := System.IOUtils.TPath.GetDocumentsPath;
{$ENDIF}
{$IFDEF WIN32}
        pathname := ExtractFilePath(ParamStr(0)) + '\Data';
{$ENDIF}
        FDSQLiteBackup1.Database := System.IOUtils.TPath.Combine(pathname,
          'default.sqlite3'); // Default Database
        FDSQLiteBackup1.DestDatabase := System.IOUtils.TPath.Combine(pathname,
          databasename + '.sqlite3');
        FDSQLiteBackup1.Backup;
        fdmProfileConnection.AddProfile(databasename + '.sqlite3', profilename);
        fdmProfileConnection.LoadProfiles;
        fCurrentProfile := fdmProfileConnection.Profiles.Items[0];
        connectDatabase;
      end else
        Application.Terminate;
    end);
end;

回答1:

Do not show any additional forms in MainForm.OnCreate/OnShow. Trying this on iOS 9.2 freeze app at "launch screen".

Instead of this, show new form asynchronously, like this:

procedure TForm4.FormShow(Sender: TObject);
begin
  TTask.Run(procedure
    begin
      TThread.Synchronize(nil, procedure // work with visual controls - only throught Synchronize or Queue
        begin
          Form5:=TForm5.Create(Application);
          Form5.ShowModal;
        end)
    end);
end;

of cource, you can separate this code to external procedures:

procedure ShowMyForm;
begin
  Form5:=TForm5.Create(Application);
  Form5.ShowModal;
end;

procedure TaskProc;
begin
  TThread.Synchronize(nil, ShowMyForm);
end;

procedure TForm4.FormShow(Sender: TObject);
begin
  TTask.Run(TaskProc);
end;

========

Another way - do not use any additional forms. Create frame and put it (at runtime) on MainForm with Align = Contents. After all needed actions - hide or release (due to ARC dont forget to set nil to frame variable) this frame.