0
votes

I was trying to make a simple animation inside a TButton procedure of a TImage rotating from a degree to another on Android using Delphi-Firemonkey (Berlin) like this:

procedure TForm1.Button1Click(Sender: TObject);
begin
while Image1.RotationAngle < 360 do begin
Image1.RotationAngle := Image1.RotationAngle+1;
Image1.Repaint;
Sleep(1);
end;
end;

I've tried with and without Image1.Repaint but the animation simply does not work, but when using a TTimer it works perfectly. Anyone has any idea how to solve this?

2
You are blocking the main thread. Use a timer so that the main thread remains responsiveDavid Heffernan
Animation requires message processing. So don't block message processing. A better way to accomplish what you are attempting is to use FMX's TFloatAnimation component to adjust the RotationAngle over time. See Using FireMonkey Animation Effects.Remy Lebeau
What is the problem using the Timer ? (on the ButtonClick you can just Enable and Disable that Timer to start and/or stop the animation). As you say it works fine because it doesn't block the main thread.Marc Guillot
Use a TFloatAnimation, set the property Rotation and start/end degree. It takes less than a minute and it's very easyAlberto Miola

2 Answers

1
votes

add FMX.Ani to uses clause, and use TAnimator in button onlick event:

procedure TForm1.Button1Click(Sender: TObject);
begin
 Image1.RotationAngle:=0;
 TAnimator.AnimateFloat(Image1,'RotationAngle',360,1,TAnimationType.InOut, TInterpolationType.Exponential );
end;

look into the docs for AnimateFloat, AnimateFloatWait, AnimateFloatDelay for detailed explanation of the params

-2
votes

Don't use any Sleep calls in the main thread, you can rotate TImage without TTimer so:

procedure TForm1.Button1Click(Sender: TObject);
var
  sText: string;
begin
  Button1.Enabled := False;
  sText := Button1.Text;
  Button1.Text := 'Wait...';
  TThread.CreateAnonymousThread(procedure
  begin
    while Image1.RotationAngle < 360 do begin
      TThread.Synchronize(nil, procedure
      begin
        Image1.RotationAngle := Image1.RotationAngle + 2;
      end);
      Sleep(10);
    end;
    TThread.Synchronize(nil, procedure
    begin
      Button1.Text := sText;
      Button1.Enabled := True;
    end);
  end).Start;
end;

Second solution: Add Anim: TFloatAnimation to the Form:

type
  TForm1 = class(TForm)
    ...
  public
    Anim: TFloatAnimation;
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Anim.Enabled := False;
  Image1.RotationAngle := 0;
  Anim.Enabled := True;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Anim := TFloatAnimation.Create(Self);
  Anim.Parent := Self;
  Anim.Duration := 1;
  Anim.StartValue := 0;
  Anim.StopValue := 360;
  Anim.PropertyName := 'Image1.RotationAngle';
end;