【问题标题】:FireMonkey controls based on iOS controls do not behave correctly基于 iOS 控件的 FireMonkey 控件行为不正确
【发布时间】:2013-07-28 23:13:56
【问题描述】:

我们开始将我们现有的 iOS (XCode) 应用程序之一移植到 Delphi FireMonkey (XE4)。到目前为止,这是一个令人惊讶的顺利过程。然而,我们遇到了一个不知道如何解决的死胡同。

我们现有的应用程序类似于新的Google Maps 应用程序。我们有一个webbrowser 控件,它显示一个包含许多图钉的谷歌地图。我们还有一个设置按钮和一个信息面板,它会在点击 pin 时出现。当按下相应的按钮/图钉时,设置和信息面板会从地图的左右两侧滑入。这一切都在 XCode 应用程序中运行良好。

以下是我们在使用 FireMonkey 端口时遇到的问题:

  • 我们无法在网络浏览器的顶部显示 FireMonkey 控件 控制。我知道这是因为网络浏览器是本地的 iOS 控件。
  • 一旦 webbrowser 控件出现,它就无法移动,例如要是我们 更改 position.x 属性,网络浏览器将保持原样。 如果我们使用内置更改为 x 属性,这也是一样的 动画。唯一似乎可以正常工作的属性是 visible

使用TMS iCL 组件,我们能够纠正第一个问题。然而,我们最担心的问题是第二个。如果无法移动 webbrowser 组件,就不可能实现使用 webbrowser(或任何原生 iOS 控件)的现代外观(滑动)UI。

有没有人找到克服这些 FireMonkey 限制的方法?

更新 1

根据雅罗斯拉夫的建议,我尝试了以下方法:

1) 使用按钮和 WebBrowser 创建了第二个表单。

unit Unit2;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes,
  System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs,
  FMX.StdCtrls, FMX.WebBrowser;

type
  TForm2 = class(TForm)
    WebBrowser1: TWebBrowser;
    Button1: TButton;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.fmx}

end.

2) 创建 Form2 作为 Form1 的子级。

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, FMX.WebBrowser,

  Unit2;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    FForm2: TForm2;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Fform2.left := Fform2.left - 5;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Fform2.left := Fform2.left + 5;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FForm2 := TForm2.Create(Self);
  FForm2.Parent := Self;
  FForm2.Left := 10;
  FForm2.Show;
  FForm2.BringToFront;
  FForm2.WebBrowser1.URL := 'www.google.com';
  FForm2.WebBrowser1.Navigate;
end;

end.

当我运行应用程序时,我看到:

以下是我的观察:

  • 单击按钮无效。
  • Form2 上的按钮不可见。
  • Form2 的Left 属性在设计器中设置为40。但是,表单显示在 0。

更新 2:

按照 cmets 中的建议,我将 Form1 源更改为:

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, FMX.WebBrowser,

  Unit2;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    Popup1: TPopup;
    WebBrowser1: TWebBrowser;
    WebBrowser2: TWebBrowser;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    FForm2: TForm2;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
  TCustomForm(Popup1.Popupform).Left := TCustomForm(Popup1.Popupform).Left - 5;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  TCustomForm(Popup1.Popupform).Left := TCustomForm(Popup1.Popupform).Left + 5;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  WebBrowser1.URL := 'www.google.com';
  WebBrowser1.Navigate;
  Popup1.Popup(FALSE);
end;

end.

不幸的是,无论是移动还是覆盖都不起作用。当前代码在引用 TCustomForm(Popup1.Popupform).Left 时抛出异常。发生异常的原因是,一旦父窗体上发生鼠标左键事件,Delphi 就会关闭弹出窗口(破坏弹出窗体)。更奇怪的是,带有浏览器的弹出窗口在它应该关闭后仍然可见,即使它在单击时没有反应。

将代码更改为 Popup1.Position.X 不会引发异常,但当然弹出窗口仍然不会移动。

此外,弹出窗口的父标签仍显示在主窗体拥有的网络浏览器下。

更新 3

我发现了一些问题,但修复它们并不能让它更好地工作。

  1. 由于某些(莫名其妙的)原因,剪切一个控件 (CTRL-X),然后选择另一个控件并粘贴 (CTRL-V) 似乎会将剪切控件粘贴到主窗体,而不是所选控件。重新设置控件的唯一方法是将其拖放到结构树中。
  2. 在将控件重新设置为 PopUp 的父级后,现在只要调用 Popup1.Popup(FALSE),就会出现异常。这很可能是因为弹出窗口显示在 Create 事件中。将其移至 OnClick 事件可消除异常。
  3. 似乎为了在单击主窗体时停止弹出窗口关闭,您应该在调用 .Popup 之前设置 StaysOpen 属性,但实际上,此属性似乎无法正常工作。例如,下面的代码使其进入 TCustomForm(Popup1.PopupForm).Left 行,但随后由于弹出表单已被破坏而引发异常!

代码:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Popup1.StaysOpen := TRUE;
  Popup1.Popup(FALSE);

  if Popup1.HasPopupForm then
    TCustomForm(Popup1.PopupForm).Left := TCustomForm(Popup1.PopupForm).Left - 5;
end;

【问题讨论】:

    标签: ios delphi delphi-xe4 firemonkey-fm3


    【解决方案1】:

    对于解决方案,我们应该知道:

    1. 每个 Firemonkey 表单都基于 Native UIView,它是 Main UIViewController 中根视图的子视图。因此,当您在 FireMonkey 表单上插入控件时,该控件将停留在 Form 的 UIView 上。
    2. 所有标准 Firemonkey 控件都没有原生 UIView。 FMX 表单具有所有 FMX 控件并对其进行管理。
    3. Firemonkey WebBrowser 基于 UIWebView,在 Firemonkey 表单的 UIView 中显示为子视图。
    4. 所有的Popup 表单都是基于透明背景的UIView。通过属性 TForm.Position、TForm.Size 设置弹出窗口的位置和大小。所以你可以用TWebBrowser在Form上创建一个透明背景的表单,设置大小和位置。

    为了解决您的问题,您可以:

    1. 创建新表单或弹出表单
    2. 为其设置大小和位置。
    3. 使用 WebBrowser 从表单中显示。在这种情况下,新表单将作为一个单独的 UIView 显示在所有 UIView 的顶部

    【讨论】:

    • +Yaroslav Brown - 我尝试了你的建议。请参阅上面的更新了解我的发现。
    • 好的。我知道了。 1.在Form 2上添加TPopup 2.在TPopup中添加任意控件 3.调用Popup1.Popup;对我来说,弹出窗口出现在 WebBrowser 上方
    • 我现在不能尝试这个,但是......你是说 a) 向弹出窗口添加控件将允许它们显示在本机 iOS 控件上,并且 b) 弹出窗口包含可以像 FireMonkey 控件一样移动本机控件。 iOS 中的 Popup 不是模态显示的吗?
    • 是的。你说的对。该弹出窗口的主要功能是使用 TopMost 属性并将其设置为 true。所以我们的表单(PopupForm)显示在所有UIView之上。尝试将 TopMost 属性设置为 true。
    • 但是弹窗可以移动吗?它是模态的,即用户可以与弹出窗口下的控件交互吗?
    猜你喜欢
    • 2016-09-09
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    • 2012-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    相关资源
    最近更新 更多