Firemonkey实现iOS程序运行时更改锁定显示方向(LockOrientations)

来源:互联网 发布:淘宝订单体验 编辑:程序博客网 时间:2024/04/30 06:37

iOS默认支持的设备方向(Device Orientation)为Portrait、LandscapeLeft、LandscapeRight,还有一个默认不支持的PortraitUpsideDown。这四种分别是竖屏Home键在下、横屏Home键在右、横屏Home键在左、竖屏Home键在上,分别对应Firemonkey中的TScreenOrientation.Portrait、TScreenOrientation.Landscape、TScreenOrientation.InvertedLandscape、TScreenOrientation.InvertedPortrait。

默认Firemonkey开发的app跟XCode默认的一样,只支持前三种。如果要设置app只支持其中的一种或其他几种,只需在工程选项设置中设置Application>Orientation为要支持的方向,IDE将自动增加一行代码设置Application.FormFactor.Orientations的值。

Application.FormFactor.Orientations := [TFormOrientation.Portrait, TFormOrientation.Landscape];

通过上面可以很方便的设置整个app的方向,但还是有两个小点不能满足:

1、为不同的form指定不同的支持方向。

2、动态(运行时)强制更改显示方向。

本来根据TApplicationFormFactor源码显示,我们可以通过修改Application.FormFactor.Orientations的值来更改屏幕方向。

TFormFactor = class(TPersistent)  private    FSize: TSize;    FOrientations: TFormOrientations;    FDevices: TDeviceKinds;    procedure SetSupportedOrientations(AOrientations: TFormOrientations); virtual;    procedure SetHeight(const Value: Integer);    procedure SetWidth(const Value: Integer);    function GetWidth: Integer;    function GetHeight: Integer;  public    constructor Create;    procedure AdjustToScreenSize;  published    property Width: Integer read GetWidth write SetWidth stored True;    property Height: Integer read GetHeight write SetHeight stored True;    property Orientations: TFormOrientations read FOrientations write SetSupportedOrientations stored True      default [TFormOrientation.Portrait, TFormOrientation.Landscape];    property Devices: TDeviceKinds read FDevices write FDevices stored True;  end;  TApplicationFormFactor = class(TFormFactor)  protected    procedure SetSupportedOrientations(AOrientations: TFormOrientations); override;  end;
procedure TApplicationFormFactor.SetSupportedOrientations(  AOrientations: TFormOrientations);var  AppService: IFMXScreenService;begin  inherited;  if TPlatformServices.Current.SupportsPlatformService(IFMXScreenService, AppService) then    AppService.SetScreenOrientation(AOrientations);end;

但进一步查看iOS平台关于IFMXScreenService的实现却发现,其SetScreenOrientation方法是空的。所以在iOS平台下无法通过该属性更改屏幕方向。

procedure TPlatformCocoaTouch.SetScreenOrientation(  AOrientations: TScreenOrientations);begin  // Not needed for iOSend;

下面的辅助函数可以实现这一功能,在FormShow事件调用即可指定当前form显示方向和锁定支持的方向。辅助单元源代码下载

unit FMX.Platform.Helper;interfaceuses FMX.Types;procedure LockOrientations(ATo: TScreenOrientation; APossibles: TScreenOrientations);implementationuses FMX.Forms, FMX.Platform, iOSapi.UIKit;procedure LockOrientations(ATo: TScreenOrientation; APossibles: TScreenOrientations);var  win : UIWindow;  App : UIApplication;  new : UIViewController;  old : UIViewController;  toio: UIInterfaceOrientation;begin  Application.FormFactor.Orientations := [];   App := TUIApplication.Wrap(TUIApplication.OCClass.sharedApplication);  win := TUIWindow.Wrap(App.windows.objectAtIndex(0));  case ATo of    TScreenOrientation.Portrait: toio := UIInterfaceOrientationPortrait;    TScreenOrientation.Landscape: toio := UIInterfaceOrientationLandscapeLeft;    TScreenOrientation.InvertedLandscape: toio := UIInterfaceOrientationLandscapeRight;    else //TScreenOrientation.InvertedPortrait      toio := UIInterfaceOrientationPortraitUpsideDown;  end;  App.setStatusBarOrientation(toio);  Application.FormFactor.Orientations := APossibles;  new := TUIViewController.Wrap(TUIViewController.alloc.init);  old := win.rootViewController;  Win.setRootViewController(new);  Win.makeKeyAndVisible;  win.setRootViewController(old);  win.makeKeyAndVisible;end;end.

通过查看android平台关于IFMXScreenService的实现,发现其实现了SetScreenOrientation方法,所以android估计可以通过Application.FormFactor.Orientations来动态更改屏幕方向。

procedure TPlatformAndroid.SetScreenOrientation(AOrientations: TScreenOrientations);begin  if (TScreenOrientation.Portrait in AOrientations) and     (TScreenOrientation.Landscape in AOrientations) and     (TScreenOrientation.InvertedPortrait in AOrientations) and     (TScreenOrientation.InvertedLandscape in AOrientations) then    MainActivity.embSetOrientation(-1)  else if TScreenOrientation.Portrait in AOrientations then    MainActivity.embSetOrientation(Integer(TScreenOrientation.Portrait))  else if TScreenOrientation.Landscape in AOrientations then    MainActivity.embSetOrientation(Integer(TScreenOrientation.Landscape))  else if TScreenOrientation.InvertedPortrait in AOrientations then    MainActivity.embSetOrientation(Integer(TScreenOrientation.InvertedPortrait))  else if TScreenOrientation.InvertedLandscape in AOrientations then    MainActivity.embSetOrientation(Integer(TScreenOrientation.InvertedLandscape));end;

1 0
原创粉丝点击