如何在Delphi XE5中使用FireMonkey检测/处理屏幕旋转

4

首先,我在Android和FireMonkey编程方面是个初学者,请谅解。

我制作了一个FireMonkey/Android应用程序,可以根据屏幕大小和方向调整其控件的大小/重新排列,但我无法弄清楚如何设置我的应用程序,在用户旋转屏幕时被调用。如果我在Firemonkey/Win32中运行并显示一个按钮,执行以下操作:

PROCEDURE TMainForm.FlipForm;
  VAR
    W,H : INTEGER;

  BEGIN
    W:=Width; H:=Height; Width:=H; Height:=W
  END;

首先,我需要捕获FormResize事件,这样我的窗体就可以按照预期进行调整。现在我想在Android上运行时也能做到同样的效果,但是当屏幕旋转时,似乎FormResize事件不会被调用,所以我的按钮等控件没有重新排列并且可能会超出屏幕范围。

因此,我的问题是,如何检测屏幕是否旋转,以便我的应用程序可以在横向和纵向模式下正常工作?


C:\Users\Public\Documents\RAD Studio\12.0\Samples\FireMonkeyMobile\Delphi\Forms 目录下有一个演示如何适应屏幕旋转的示例。 - Ken White
3个回答

10

如果您无法使表单的OnResize事件起作用,则可以通过以下方式订阅FMX方向更改消息:

uses
  FMX.Forms, FMX.Messages, FMX.Types;

//In the definition of TFooForm you define:
FOrientationChangedId: Integer;
procedure OrientationChangedHandler(const Sender: TObject; const Msg: TMessage);

//Subscribe to orientation change events in OnCreate or similar
FOrientationChangedId := TMessageManager.DefaultManager.SubscribeToMessage(
  TOrientationChangedMessage, OrientationChangedHandler);

//Unsubscribe from orientation change events in OnDestroy or similar
TMessageManager.DefaultManager.Unsubscribe(
  TOrientationChangedMessage, FOrientationChangedId);

procedure TFooForm.OrientationChangedHandler(const Sender: TObject; const Msg: TMessage);
begin
  Log.d('Orientation has changed');
end;

非常好。现在这个程序可以运行了,但是似乎我没有得到正确的屏幕尺寸,只有1280x800的屏幕尺寸(减去底部菜单栏),即使我的平板电脑是2560x1600。我该如何让Android理解,我可以处理任何和所有的屏幕尺寸(我自己调整按钮等),并且它不应用任何缩放,而只允许我利用全屏尺寸?当我在我的重新流动代码中读取屏幕大小时,它总是返回1280x752(横向)或800x1232(纵向)。 - HeartWare
为了更方便的开发,我已经将我的主窗体设置为预定义的1280x800大小。这样可以更容易地使用设计器。但是我仍然希望能够使用目标设备的全尺寸,并对我的控件进行自己的缩放和/或重新排列... - HeartWare
我认为你可以使用以下方式获取固有的屏幕缩放比:var ScreenService: IFMXScreenService; Scale: Single; ... if TPlatformServices.Current.SupportsPlatformService(IFMXScreenService, IInterface(ScreenService)) then Scale := ScreenService.GetScreenScale else Scale := 1; - blong

6

为了使用IFMXScreenService,最好先测试一下平台是否支持它,如果不支持,会导致"Segmentation Fault"错误。我是这样使用它的:

uses FMXPlatform;

...

procedure TForm2.FormResize(Sender: TObject);
var
  ScreenService: IFMXScreenService;
begin
  if TPlatformServices.Current.SupportsPlatformService(IFMXScreenService, IInterface(ScreenService)) then
  begin
    if ScreenService.GetScreenOrientation in [TScreenOrientation.soPortrait, TScreenOrientation.soInvertedPortrait] then
      ShowMessage('Portrait Orientation')
    else
     Begin
      ShowMessage('Landscape Orientation');

     End;

  end;
end;

5
您还可以采用以下方法: 当应用程序旋转时,将调用 TForm.OnResize。因此,您可以在此事件上设置处理程序,并通过服务 IFMXScreenService.GetScreenOrientation 检查当前方向。

在OnResize事件中,我们可以通过比较窗体的宽度和高度来确定其方向,这不是很简单吗?实际上,我期望所有控件都有一个Orientation:TOrientation只读属性来返回它们的“方向”,而像TrackBars这样具有不同方向含义的控件将在那里实现自己的逻辑。 - George Birbilis

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