首先,VCL 的 TPageControl 是没有切入切出动画的,所以,这里要做的是给 VCL 的 TPageControl 做动画支持。当然,虽然咱们说的是 QAnimation 教程,但关注的重点不是 QAnimation,而是如何给 TPageControl 添加动画效果,QAnimation 只是一个动画控制器而已,你完全可以用自己的 Timer 来替代。
第一步:当然是为 PageControl 创建 N 个 TabSheet 页面,这一步我们省略说明。
第二步:加入动画控制代码。
- 引用 qdac_ani 单元,或者在界面上加上你的 Timer,然后在你的 Timer 的 OnTimer 事件中处理动画。
- 我这个 Demo 是要求不断的切换,类似网页上常见的 slider 效果,所以我在 FormCreate 事件中添加处理代码:
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, qdac_ani, Vcl.Imaging.pngimage, Vcl.ExtCtrls; type TForm1 = class(TForm) PageControl1: TPageControl; TabSheet1: TTabSheet; TabSheet2: TTabSheet; Label1: TLabel; Label2: TLabel; Edit1: TEdit; Image1: TImage; procedure FormCreate(Sender: TObject); private { Private declarations } FAnimation: IQAnimation; public { Public declarations } end; var Form1: TForm1; implementation uses qstring; {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); var I: Integer; begin for I := 0 to PageControl1.PageCount - 1 do PageControl1.Pages[I].TabVisible := false; PageControl1.ActivePage := TabSheet1; //创建动画控制器 FAnimation := CreateAnimation( procedure(Sender: IQAnimation; AEvent: TQAnimationEvent) var APage: TTabSheet; begin case AEvent of GotoTime: begin //因为动画是将下一页切入,所以取当前活动页的下一页进行处理 APage := PageControl1.Pages[(PageControl1.ActivePageIndex + 1) mod PageControl1.PageCount]; APage.SetBounds(PageControl1.ActivePage.Left,APage.Height - Trunc(APage.Height * Sender.NormalizedTime),PageControl1.ActivePage.Width,PageControl1.ActivePage.Height); end; EnterDelay: begin APage := PageControl1.Pages[(PageControl1.ActivePageIndex + 1) mod PageControl1.PageCount]; APage.Align := alClient; PageControl1.ActivePage := APage; end; ExitDelay: begin //因为动画是将下一页切入,所以取当前活动页的下一页进行处理 APage := PageControl1.Pages[(PageControl1.ActivePageIndex + 1) mod PageControl1.PageCount]; //VCL的 TabSheet 默认是alClient,那样没法调整坐标,所以改下 APage.Align := alNone; //不可见页实际上是隐藏的,设置为true显示出来 APage.Visible := true; //动画页切到前面,后面谁也不知道呀 APage.BringToFront; end; end; end); FAnimation.Duration := 1;//动画时长设置为1秒 FAnimation.Interpolation := TQInterpolationType.Bounce;//动画方式设置为弹跳 FAnimation.DelayTime := 5;//动画延迟间隔设置为5秒 FAnimation.Loop := true;//循环 FAnimation.Start;//启动动画 end;
QAnimation 提供了一个 CreateXXAnimation 的一组接口函数,方便创建不同类型的动画。因为这个控制操作相对复杂一些,所以我直接用了 CreateAnimation,自己去实现对页面属性的控制。然后上面的动画控制参数都有说明,我就不缀述,自己看下就好。重点大家关注下对页面切换的处理,在我们开始切入新页时,要将新页的 Align 设置为 alNone,否是你调整坐标是动不起来的,然后还需要将要新页给提到最前显示,否则在后边用户也看不到,对不对?至于动画过程中,实际上就是直接调整的顶部的坐标,然后实现的动画方式是弹跳的效果。看一下实际运行的效果:
QAnimation 提供的额外动画控制单元包含下面的函数,见名知义,不做多说:// 最简单的用户自定义处理动画 function CreateAnimation(ACallback: TQAnimationNotifyCallback) : IQAnimation; overload; function CreateAnimation(ACallback: TQAnimationNotifyEvent) : IQAnimation; overload; // 浮点动画处理 function CreateFloatAnimation(ACallback: TQAnimationNotifyCallback) : IQFloatAnimation; overload; function CreateFloatAnimation(ACallback: TQAnimationNotifyEvent) : IQFloatAnimation; overload; // 整数动画处理 function CreateIntAnimation(ACallback: TQAnimationNotifyCallback) : IQIntAnimation; overload; function CreateIntAnimation(ACallback: TQAnimationNotifyEvent) : IQIntAnimation; overload; // 布尔动画处理 function CreateBooleanAnimation(ACallback: TQAnimationNotifyCallback): IQBoolAnimation; overload; function CreateBooleanAnimation(ACallback: TQAnimationNotifyEvent): IQBoolAnimation; overload; // 颜色动画处理 function CreateColorAnimation(ACallback: TQAnimationNotifyCallback) : IQColorAnimation; overload; function CreateColorAnimation(ACallback: TQAnimationNotifyEvent) : IQColorAnimation; overload; function CreateAlphaColorAnimation(ACallback: TQAnimationNotifyCallback) : IQAlphaColorAnimation; overload; function CreateAlphaColorAnimation(ACallback: TQAnimationNotifyEvent) : IQAlphaColorAnimation; overload; // 用户自定义控制特定属性的动画,具体的项目的值由用户自行决定 function CreatePropertyAnimation(AObject: TObject; APropPath: String; ACallback: TQAnimationNotifyCallback): IQPropertyAnimation; overload; function CreatePropertyAnimation(AObject: TObject; APropPath: String; ACallback: TQAnimationNotifyEvent): IQPropertyAnimation; overload; function CreateIntPropertyAnimation(AObject: TObject; APropPath: String; ACallback: TQAnimationNotifyCallback): IQIntAnimation; overload; function CreateIntPropertyAnimation(AObject: TObject; APropPath: String; ACallback: TQAnimationNotifyEvent): IQIntAnimation; overload; function CreateFloatPropertyAnimation(AObject: TObject; APropPath: String; ACallback: TQAnimationNotifyCallback): IQFloatAnimation; overload; function CreateFloatPropertyAnimation(AObject: TObject; APropPath: String; ACallback: TQAnimationNotifyEvent): IQFloatAnimation; overload; function CreateColorPropertyAnimation(AObject: TObject; APropPath: String; ACallback: TQAnimationNotifyCallback): IQColorAnimation; overload; function CreateColorPropertyAnimation(AObject: TObject; APropPath: String; ACallback: TQAnimationNotifyEvent): IQColorAnimation; overload; function CreateAlphaColorPropertyAnimation(AObject: TObject; APropPath: String; ACallback: TQAnimationNotifyCallback): IQAlphaColorAnimation; overload; function CreateAlphaColorPropertyAnimation(AObject: TObject; APropPath: String; ACallback: TQAnimationNotifyEvent): IQAlphaColorAnimation; overload;
第三步:编译运行程序。
另外,QAnimation 不是免费的,价格暂定 99 元,FMX+VCL 同时支持,也就是说一套代码。你可以认为它是 FMX.Ani 的增强版,如果心疼的话,直接自己参考 FMX.Ani 单元写下就好。