Delphi FMX TAnimator. Как оживить TPointF
У меня есть TScrollbox в моей форме. На Scrollbox помещается TLayout, который шире и выше, чем область просмотра устройства, поэтому полосы прокрутки по горизонтали и вертикали отображаются, и пользователь может вручную перемещать макет.
У меня также есть настройка жестов, так что пользователь может нажать Scrollbox и вернуть макет в исходное положение (0,0).
procedure TfrmMain.ScrollBox1Gesture(Sender: TObject;
const EventInfo: TGestureEventInfo; var Handled: Boolean);
begin
if EventInfo.GestureID = System.UITypes.igiLongTap then
begin
ScrollBox1.ViewportPosition := PointF(0, 0);
ScrollBox1.RealignContent;
end;
Теперь это прекрасно работает, но как это происходит довольно быстро. Я подумал, что, возможно, я мог бы использовать:
TAnimator.AnimateFloat(Scrollbox1, 'ScrollBox1.ViewportPosition.X', 0, 0.3);
сделать движение из текущей позиции обратно в 0 более плавным, но, конечно, это никогда не сработает, потому что вы не можете присвоить значение PointF.X
или же PointF.Y
непосредственно (и, следовательно, ни аниматор).
Так как это можно сделать? Спасибо
1 ответ
Поскольку встроенная программа PointAnimation отсутствует, она написана самостоятельно.
type
TPointAnimation = class(TCustomPropertyAnimation)
private
FStartFloat: TPointF;
FStartFromCurrent: Boolean;
FStopFloat: TPointF;
protected
procedure FirstFrame; override;
procedure ProcessAnimation; override;
public
constructor Create(AOwner: TComponent); override;
published
property AnimationType default TAnimationType.In;
property AutoReverse default False;
property Delay;
property Duration nodefault;
property Enabled default False;
property Interpolation default TInterpolationType.Linear;
property Inverse default False;
property Loop default False;
property OnFinish;
property OnProcess;
property PropertyName;
property StartFromCurrent: Boolean read FStartFromCurrent write
FStartFromCurrent default False;
property StartValue: TPointF read FStartFloat write FStartFloat stored True;
property StopValue: TPointF read FStopFloat write FStopFloat stored True;
property Trigger;
property TriggerInverse;
end;
constructor TPointAnimation.Create(AOwner: TComponent);
begin
inherited;
Duration := 0.2;
FStartFloat := PointF(0, 0);
FStopFloat := PointF(0, 0);
end;
procedure TPointAnimation.FirstFrame;
var
T: TRttiType;
P: TRttiProperty;
begin
if StartFromCurrent then
begin
T := SharedContext.GetType(FInstance.ClassInfo);
if T <> nil then
begin
P := T.GetProperty(FPath);
if (P <> nil) and (P.PropertyType.TypeKind = tkRecord) then
StartValue := P.GetValue(FInstance).AsType<TPointF>;
end;
end;
end;
procedure TPointAnimation.ProcessAnimation;
var
newPoint: TPointF;
T: TRttiType;
P: TRttiProperty;
begin
if FInstance <> nil then
begin
T := SharedContext.GetType(FInstance.ClassInfo);
if T <> nil then
begin
P := T.GetProperty(FPath);
if (P <> nil) and (P.PropertyType.TypeKind = tkRecord) then begin
newPoint := PointF(InterpolateSingle(FStartFloat.X, FStopFloat.X, NormalizedTime),
InterpolateSingle(FStartFloat.Y, FStopFloat.Y, NormalizedTime));
P.SetValue(FInstance, TValue.From<TPointF>(newPoint));
end;
end;
end;
end;
Объявите поле внутри частного раздела форм
ani: TPointAnimation;
Создать экземпляр во время FormCreate
ani := TPointAnimation.Create(Self);
ani.PropertyName := 'ViewportPosition';
ani.StartFromCurrent := true;
ani.Duration := 0.3;
ScrollBox1.AddObject(ani);
и запустить его при необходимости
ani.Start;