Android

时间:2016-08-25 10:31:09

标签: android delphi modal-dialog firemonkey blocking

我正在为一个客户从较旧的AppMethod版本移植到旧版项目(适用于iOS和Android的应用程序)到最新的RAD Studio版本(10.0 Berlin)。 MessageDlg和类似项目在项目中经常使用,但这不再适用。应用程序显示一条消息,Android上不支持模态对话框。我知道并理解为什么Android平台会出现这种情况(所以请不要通过引用解释将此问题标记为公开 - 我要求其他东西!)。

Firemonkey允许设置一个匿名函数,在用户点击对话框中的按钮或关闭按钮后异步执行。但是,通常的代码取决于用户决策或在对话框之后必须执行的代码,无论用户点击哪个按钮。例如,对话框必须在正在进行的操作过程中询问用户他的决定。然后,进一步的操作取决于用户的决定(这可能还包括在当前应用程序中停止进一步的代码执行!)。由于RAD Studio不支持在Android上阻止对话框,我似乎被迫分解我的代码 - 从一个功能到多个功能(可读性更差......)。当存在嵌套函数调用以及可能需要用户交互的模式对话框时,这会变得更加复杂。

还有办法以某种方式模拟阻止对话框吗?它不一定是完美的。我只是不想重写很多代码,甚至将小代码片段外包到许多单独的函数中,无论在哪里需要用户交互。

好的,我认为以下“脏”的解决方案对我来说可能就足够了:

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.DialogService,
  FMX.Controls.Presentation, FMX.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  blockDlg: array[0..99] of Boolean;
  blockDlgIdx: Integer = 0;

implementation

{$R *.fmx}

procedure NShowMessageAsync(AMessage: String);
begin
  TDialogService.ShowMessage(AMessage);
end;

procedure NShowMessageSync(AMessage: String);
var
  locBlockIdx: Integer;
begin
  if blockDlgIdx = Length(blockDlg)-1 then blockDlgIdx := 0 else Inc(blockDlgIdx);
  locBlockIdx := blockDlgIdx;

  blockDlg[locBlockIdx] := true;
  TDialogService.ShowMessage(AMessage,
    procedure(const AResult: TModalResult)
    begin
      blockDlg[locBlockIdx] := false;
    end);
  while blockDlg[locBlockIdx] do begin
    Sleep(40);
    Application.ProcessMessages();
  end;
end;

procedure NMessageDialogAsync(const AMessage: string; const ADialogType: TMsgDlgType;
  const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn;
  const AHelpCtx: LongInt);
begin
  TDialogService.MessageDialog(AMessage, ADialogType, AButtons, ADefaultButton,
    AHelpCtx, procedure(const AResult: TModalResult) begin end);
end;

function NMessageDialogSync(const AMessage: string; const ADialogType: TMsgDlgType;
  const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn;
  const AHelpCtx: LongInt): TModalResult;
var
  locBlockIdx: Integer;
  LModalResult: TModalResult;
begin
  Result := -1;
  if blockDlgIdx = Length(blockDlg)-1 then blockDlgIdx := 0 else Inc(blockDlgIdx);
  locBlockIdx := blockDlgIdx;

  blockDlg[locBlockIdx] := true;
  TDialogService.MessageDialog(AMessage, ADialogType, AButtons, ADefaultButton, AHelpCtx,
    procedure(const AResult: TModalResult)
    begin
      LModalResult := AResult;
      blockDlg[locBlockIdx] := false;
    end);

  while blockDlg[locBlockIdx] do begin
    Sleep(40);
    Application.ProcessMessages();
  end;

  Result := LModalResult;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  mr: TModalResult;
begin
  mr := NMessageDialogSync('1',
    System.UITypes.TMsgDlgType.mtInformation,
    [System.UITypes.TMsgDlgBtn.mbYes, System.UITypes.TMsgDlgBtn.mbNo, System.UITypes.TMsgDlgBtn.mbCancel],
    System.UITypes.TMsgDlgBtn.mbYes,
    0);
  NShowMessageSync(IntToStr(mr));
  mr := NMessageDialogSync('2',
    System.UITypes.TMsgDlgType.mtWarning,
    [System.UITypes.TMsgDlgBtn.mbYesToAll, System.UITypes.TMsgDlgBtn.mbAbort],
    System.UITypes.TMsgDlgBtn.mbAbort,
    0);
  NShowMessageSync(IntToStr(mr));
  mr := NMessageDialogSync('3',
    System.UITypes.TMsgDlgType.mtInformation,
    [System.UITypes.TMsgDlgBtn.mbIgnore, System.UITypes.TMsgDlgBtn.mbAll, System.UITypes.TMsgDlgBtn.mbHelp, System.UITypes.TMsgDlgBtn.mbClose],
    System.UITypes.TMsgDlgBtn.mbClose,
    0);
  NShowMessageSync(IntToStr(mr));

  Form1.Fill.Kind := TBrushKind.Solid;
  if Form1.Fill.Color = TAlphaColors.Red then
    Form1.Fill.Color := TAlphaColors.Blue
  else
    Form1.Fill.Color := TAlphaColors.Red;
end;

end.

不是很干净,但至少我可以使用它一段时间。

0 个答案:

没有答案