unit MainWnd;

interface

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

type
  TMainWindow = class(TForm)
    Layout1: TLayout;
    Image1: TImage;
    Image2: TImage;
    Image3: TImage;
    Label1: TLabel;
    FloatAnimation1: TFloatAnimation;
    procedure FloatAnimation1Process(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    Angle: Integer;
  public
    procedure Rotated;
  end;

var
  MainWindow: TMainWindow;

implementation

{$R *.fmx}

uses Macapi.ObjectiveC, Macapi.ObjCRuntime, iOSapi.CocoaTypes, iOSapi.UIKit,
  iOSapi.Foundation, System.TypInfo;

procedure TMainWindow.FormCreate(Sender: TObject);
begin
  Image1.Height := Image1.Width;
  Image2.Width := Image2.Height;
  Image3.Width := Image3.Height;
  Rotated;
end;

procedure TMainWindow.Rotated;
begin
  // This is the new orientation
  case TUIApplication.wrap(TUIApplication.OCClass.SharedApplication).statusBarOrientation of
    UIDeviceOrientationPortrait: Angle := 0;
    UIDeviceOrientationLandscapeLeft: Angle := 1;
    UIDeviceOrientationLandscapeRight: Angle := 3;
    UIDeviceOrientationPortraitUpsideDown: Angle := 2;
  end;

  // Here we keep the main layout on the full screen (Align does not work with rotation)
  if Angle in [1, 3] then
    Layout1.SetBounds((FLastWidth - FLastHeight) / 2,
      (FLastHeight - FLastWidth) / 2, FLastHeight, FLastWidth)
  else
    Layout1.SetBounds(0, 0, FLastWidth, FLastHeight);

  // The animation will look nicer, if 90 degrees rotation is performed, rather than 270
  if (Image1.RotationAngle = 0) and (Angle * 90 = 270) then
  begin
    Image1.RotationAngle := 360;
    FloatAnimation1Process(nil);
  end else
  if (Image1.RotationAngle = 270) and (Angle * 90 = 0) then
  begin
    Image1.RotationAngle := -90;
    FloatAnimation1Process(nil);
  end;

  // First rotate the main layout, then animate rotation of the children
  Layout1.RotationAngle := 360 - Angle * 90;
  FloatAnimation1.StopValue := Angle * 90;
  FloatAnimation1.Start;
end;

procedure TMainWindow.FloatAnimation1Process(Sender: TObject);
begin
  // It works MUCH faster with a single animation's result being applied
  // to all objects, rather than separate animations for each object.
  Image2.RotationAngle := Image1.RotationAngle;
  Label1.RotationAngle := Image1.RotationAngle;
end;

end.

