for B in AButtons do begin if ButtonIndex < ButtonsCount then begin LCaptions.Items[ButtonIndex] := StringToJString(ButtonCaptions[B]); if ADefaultButton = B then begin DefaultButton := ModalResults[B]; end; case ButtonIndex of 0: PosButton := ModalResults[B]; 1: NegButton := ModalResults[B]; 2: NeutralButton := ModalResults[B]; end; end; Inc(ButtonIndex); end;
DialogFactory := TJFMXDialogFactory.JavaClass.getFactory; if DialogFactory <> nil then begin CallInUIThreadAndWaitFinishing( procedure begin AlertDialog := DialogFactory.createMessageDialog(MainActivity, GetNativeTheme, StringToJString(AMessage), Ord(ADialogType), LCaptions, PosButton, NegButton, NeutralButton);
if AlertDialog <> nil then begin if DefaultButton > 0 then begin AlertDialog.getRealDialog.setCancelable(MessageDialog_Canceleable); AlertDialog.getRealDialog.setCanceledOnTouchOutside( MessageDialog_CanceledOnTouchOutsid); end else begin AlertDialog.getRealDialog.setCancelable(False); AlertDialog.getRealDialog.setCanceledOnTouchOutside(False); end; if Assigned(ACloseDialogProc) then begin DialogListener := TFMXDialogListener.Create( procedure (const AResult: TModalResult; const AValues: array of string) begin ACloseDialogProc(AResult); end, DefaultButton); DialogListener.ParentList := FAlertListeners; AlertDialog.setListener(DialogListener); end; AlertDialog.show; end; end); end; end;
【第七步】 找到 function TPlatformAndroid.InputQuery(const ACaption: string; const APrompts: array of string; var AValues: array of string; const ACloseQueryFunc: TInputCloseQueryFunc): Boolean; 修改这个函数的代码,改成如下内容。 //Fix By Flying Wang function TPlatformAndroid.InputQuery(const ACaption: string; const APrompts: array of string; var AValues: array of string; const ACloseQueryFunc: TInputCloseQueryFunc): Boolean; var ARetVal: Integer; begin //raise ENotImplemented.CreateFmt(SNotImplementedOnPlatform, [SBlockingDialogs]); Result := False; ARetVal := -1; InputQuery(ACaption, APrompts, AValues, procedure(const AResult: TModalResult; const AValues: array of string) begin ARetVal := AResult; if ARetVal = mrOK then if Assigned(ACloseQueryFunc) then ACloseQueryFunc(AValues); end); while ARetVal < 0 do begin Sleep(BlockingMessageWaitMilliSeconds); Application.ProcessMessages; end; Result := ARetVal = mrOK; end;
【第八步】 找到 procedure TPlatformAndroid.InputQuery(const ACaption: string; const APrompts, ADefaultValues: array of string; const ACloseQueryProc: TInputCloseQueryProc); 修改这个函数的代码,改成如下内容。 //Fix By Flying Wang procedure TPlatformAndroid.InputQuery(const ACaption: string; const APrompts, ADefaultValues: array of string; const ACloseQueryProc: TInputCloseQueryProc); var DialogFactory: JFMXDialogFactory; QueryDialog: JFMXStandardDialog; JavaPrompts: TJavaObjectArray<JString>; JavaDefaultValues: TJavaObjectArray<JString>; DialogListener: TFMXDialogListener; LCaptions: TJavaObjectArray<JString>; I: Integer; begin if Length(ADefaultValues) < Length(APrompts) then raise EInvalidOperation.Create(SPromptArrayTooShort); if Length(APrompts) = 0 then raise EInvalidOperation.Create(SPromptArrayEmpty);
JavaPrompts := TJavaObjectArray<JString>.Create(Length(APrompts)); JavaDefaultValues := TJavaObjectArray<JString>.Create(Length(ADefaultValues)); for I := 0 to Length(APrompts) - 1 do JavaPrompts[I] := StringToJString(APrompts[I]); for I := 0 to Length(ADefaultValues) - 1 do JavaDefaultValues[I] := StringToJString(ADefaultValues[I]); LCaptions := TJavaObjectArray<JString>.Create(2); LCaptions.Items[0] := StringToJString(ButtonCaptions[TMsgDlgBtn.mbOK]); LCaptions.Items[1] := StringToJString(ButtonCaptions[TMsgDlgBtn.mbCancel]); DialogFactory := TJFMXDialogFactory.JavaClass.getFactory; if DialogFactory <> nil then begin CallInUIThreadAndWaitFinishing( procedure begin QueryDialog := DialogFactory.createInputQueryDialog(MainActivity, GetNativeTheme, StringToJString(ACaption), JavaPrompts, JavaDefaultValues, LCaptions); if QueryDialog <> nil then begin QueryDialog.getRealDialog.setCancelable(MessageDialog_Canceleable); QueryDialog.getRealDialog.setCanceledOnTouchOutside( MessageDialog_CanceledOnTouchOutsid); if Assigned(ACloseQueryProc) then begin DialogListener := TFMXDialogListener.Create(ACloseQueryProc, ModalResults[TMsgDlgBtn.mbCancel]); DialogListener.ParentList := FAlertListeners; QueryDialog.setListener(DialogListener); end; QueryDialog.show; end; end); end; end;
//Fix By Flying Wang. constructor TFMXDialogListener.Create(const AInputCloseQueryProc: TInputCloseQueryProc; ADefaultButtonIndex: Integer); begin inherited Create; FDefaultButtonIndex := ADefaultButtonIndex; FInputCloseQueryProc := AInputCloseQueryProc; end;
//Fix By Flying Wang. procedure TFMXDialogListener.DoDialogClosed; begin //非常幸运的是,正常的返回都大于 0 。 if FModalResult <= 0 then FModalResult := FDefaultButtonIndex; FInputCloseQueryProc(FModalResult, FValues); if FParentList <> nil then FParentList.Remove(Self); FParentList := nil; end;
----------------------------------------------
(C)(P)Flying Wang
【第一步】 打开 FMX.VirtualKeyboard.Android 找到 function TVirtualKeyboardAndroid.GetVirtualKeyboardState: TVirtualKeyboardStates; begin if FError then Result := [TVirtualKeyboardState.Error] else Result := []; if IsAutoShow then Result := Result + [TVirtualKeyboardState.AutoShow]; if FTransient then Result := Result + [TVirtualKeyboardState.Transient]; if not FError then begin if FState = TvkbState.Shown then Result := Result + [TVirtualKeyboardState.Visible]; end; end;
将上面的函数修改为 //Fix Error By 爱吃猪头肉 & Flying Wang function ObtainKeyboardRect: TRect; var ContentRect, TotalRect: JRect; begin ContentRect := TJRect.Create; TotalRect := TJRect.Create; MainActivity.getWindow.getDecorView.getWindowVisibleDisplayFrame(ContentRect); MainActivity.getWindow.getDecorView.getDrawingRect(TotalRect); Result := TRectF.Create(ConvertPixelToPoint(TPointF.Create(TotalRect.left, TotalRect.top + ContentRect.height)), ConvertPixelToPoint(TPointF.Create(TotalRect.right, TotalRect.bottom))).Truncate; end;
function GetVirtualKeyboardHeight: Single; var KeyboardRect: TRect; begin Result := 0; KeyboardRect := ObtainKeyboardRect; //目前设置为 低于 30 就算隐藏。 if (KeyboardRect.Width < 30) or (KeyboardRect.Height < 30) then begin exit; end; Result := KeyboardRect.Height; end;
procedure ProcessVirtualKeyboardEvent; var VirtualKeyboard: IFMXVirtualKeyboardService; VirtualKeyboardAndroid: TVirtualKeyboardAndroid; begin if TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(VirtualKeyboard)) then begin VirtualKeyboardAndroid := TVirtualKeyboardAndroid(VirtualKeyboard); VirtualKeyboardAndroid.GetVirtualKeyBoardState; end; end;
function HideInputForFixVirtualKeyboardEvent :Boolean; var TextView: JFMXTextEditorProxy; begin Result := False; try Screen.ActiveForm.Focused := nil; TextView := MainActivity.getTextEditorProxy; CallInUIThread( procedure begin TextView.setFocusable(false); TextView.setFocusableInTouchMode(false); end); Result := True; except Application.HandleException(Screen.ActiveForm); end; end;
function TVirtualKeyboardAndroid.GetVirtualKeyboardState: TVirtualKeyboardStates; var KeyboardRect: TRect; begin if FError then Result := [TVirtualKeyboardState.Error] else Result := []; if IsAutoShow then Result := Result + [TVirtualKeyboardState.AutoShow]; if FTransient then Result := Result + [TVirtualKeyboardState.Transient]; if not FError then begin if (FState = TvkbState.Shown) then begin if GetVirtualKeyboardHeight < 1 then begin KeyboardRect := ObtainKeyboardRect; TThread.Synchronize(nil, procedure begin SetState(TVirtualKeyboardAndroid.TvkbState.Hidden); TMessageManager.DefaultManager.SendMessage(Self, TVKStateChangeMessage.Create(false, ObtainKeyboardRect), True); end); end; end; if FState = TvkbState.Shown then Result := Result + [TVirtualKeyboardState.Visible]; end; end;
4 或者对每个输入框的按下事件处理。 uses FMX.Platform, FMX.VirtualKeyboard; procedure TForm1.Edit1Click(Sender: TObject); var VirtualKeyboard: IFMXVirtualKeyboardService; begin {$IFDEF ANDROID} //当没有选中自己的时候不自动弹出。 if Focused = IControl(Edit1) then exit; if GetVirtualKeyboardHeight < 1 then begin if TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(VirtualKeyboard)) then begin if not (TVirtualKeyboardState.Visible in VirtualKeyboard.VirtualKeyBoardState) then begin if (TVirtualKeyboardState.AutoShow in VirtualKeyboard.VirtualKeyBoardState) then VirtualKeyboard.ShowVirtualKeyboard(Edit1); end; end; end; {$ENDIF} end;
----------------------------------------------
(C)(P)Flying Wang