FMX.ImageSlider.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. // ***************************************************************************
  2. //
  3. // FMXComponents: Firemonkey Opensource Components Set from China
  4. //
  5. // A Simple Firemonkey Image Slider Component
  6. //
  7. // Copyright 2017 谢顿 (zhaoyipeng@hotmail.com)
  8. //
  9. // https://github.com/zhaoyipeng/FMXComponents
  10. //
  11. // ***************************************************************************
  12. // version history
  13. // 2017-01-20, v0.1.0.0 : first release
  14. // 2018-01-31, v0.2.0.0 : merged with loko's change
  15. // 2018-03-21, v0.3.0.0 : merged with kwon hwang-jung's change 2018-03-02
  16. // 1. add three Add methods to add bitmap directly
  17. // 2. add Next, Prev methods
  18. // 3. add AutoSlider property can auto slide
  19. // 4. add TimerInterval to control AutoSlider interval
  20. // 5. use ActivePage property move page, ex)ActivePage := 1
  21. // 6. add Datas property, can set tagstring on each page
  22. // 2018-03-21, v0.4.0.0 : merged with Mikkao's change 2018-03-01
  23. // 1. change OnPageChange event to TPageChangeEvent
  24. // 2. add OnPageAnimationFinish event
  25. // 3. add OnCanDragBegin event
  26. // 2018-03-21, v0.5.0.0 :
  27. // 1. rewrite slide method, now can support loop
  28. // 2018-03-22, v0.6.0.0 :
  29. // 1. add dot indicator, support dynamic change dot active/inactive color
  30. unit FMX.ImageSlider;
  31. interface
  32. {$I FMXComponents.inc}
  33. uses
  34. System.Classes,
  35. System.Generics.Collections,
  36. System.Types,
  37. System.UITypes,
  38. System.SysUtils,
  39. FMX.Types,
  40. FMX.Controls,
  41. FMX.Layouts,
  42. FMX.Objects,
  43. FMX.Ani,
  44. FMX.Utils,
  45. FMX.Graphics,
  46. FMX.ComponentsCommon,
  47. UI.Base, UI.Standard;
  48. type
  49. TPageChangeEvent = procedure(Sender: TObject; NewPage, OldPage: Integer) of object;
  50. TPageAnimationFinishEvent = procedure(Sender: TObject; NewPage: Integer) of object;
  51. TCanBeginDragEvent = procedure(Sender: TObject; var CanBegin: Boolean) of object;
  52. TFMXImageSlider = class;
  53. TSliderDots = class(TControl)
  54. private
  55. FDotContainer: TLayout;
  56. FDotSize: Single;
  57. FActiveColor: TAlphaColor;
  58. FInActiveColor: TAlphaColor;
  59. FActiveIndex: Integer;
  60. procedure SetDotCount(const Value: Integer);
  61. function GetDotCount: Integer;
  62. procedure CreateDotShape;
  63. procedure SetDotSize(const Value: Single);
  64. procedure SetActiveColor(const Value: TAlphaColor);
  65. procedure SetInActiveColor(const Value: TAlphaColor);
  66. procedure SetActiveIndex(const Value: Integer);
  67. protected
  68. procedure HitTestChanged; override;
  69. function GetDot(Index: Integer): TControl;
  70. {$IFDEF VER320_up}
  71. procedure DoResized; override;
  72. {$ELSE}
  73. procedure Resize; override;
  74. {$ENDIF}
  75. public
  76. constructor Create(AOwner: TComponent); override;
  77. property ActiveIndex: Integer read FActiveIndex write SetActiveIndex;
  78. property DotCount: Integer read GetDotCount write SetDotCount;
  79. property DotSize: Single read FDotSize write SetDotSize;
  80. property ActiveColor: TAlphaColor read FActiveColor write SetActiveColor;
  81. property InActiveColor: TAlphaColor read FInActiveColor write SetInActiveColor;
  82. end;
  83. [ComponentPlatformsAttribute(TFMXPlatforms)]
  84. TFMXImageSlider = class(TLayout)
  85. private
  86. FContainer: TControl;
  87. FIsTimer: Boolean;
  88. FAutoSlider: Boolean;
  89. FTimer: TTimer;
  90. FPages: TList<TControl>;
  91. FActivePage: Integer;
  92. FIsMove: Boolean;
  93. FStartDrag: Boolean;
  94. FBeforeDrag: Boolean;
  95. FDownPos: TPointF;
  96. FDownIndex: Integer;
  97. FAnimation: TAnimation;
  98. FOnPageAnimationFinish: TPageAnimationFinishEvent;
  99. FOnCanDragBegin: TCanBeginDragEvent;
  100. FOnItemTap: TTapEvent;
  101. FOnItemClick: TNotifyEvent;
  102. FOnPageChange: TPageChangeEvent;
  103. FAnimationInterval: Integer;
  104. FTransitionLayouts: array of TControl;
  105. FTranstionIsIn: Boolean;
  106. FTranstionStartX: Single;
  107. FDots: TSliderDots;
  108. FIsCanDrag: Boolean;
  109. procedure MoveToActivePage(IsIn: Boolean = True);
  110. procedure OnTimer(Sender: TObject);
  111. procedure AnimationProcess(Sender: TObject);
  112. procedure AnimationFinished(Sender: TObject);
  113. function GetAnimateDuration: Single;
  114. function GetDatas(Index: Integer): string;
  115. function GetPageCount: Integer;
  116. function GetTimerInterval: Integer;
  117. procedure SetActivePage(const Value: Integer); { change }
  118. procedure SetAnimateDuration(const Value: Single);
  119. procedure SetAutoSlider(const Value: Boolean);
  120. procedure SetPageCount(const Value: Integer);
  121. procedure SetDatas(Index: Integer; const Value: string);
  122. function SetDragBegin: Boolean;
  123. function GetDotsVisible: Boolean;
  124. procedure SetDotsVisible(const Value: Boolean);
  125. function GetDotActiveColor: TAlphaColor;
  126. function GetDotInActiveColor: TAlphaColor;
  127. procedure SetDotActiveColor(const Value: TAlphaColor);
  128. procedure SetDotInActiveColor(const Value: TAlphaColor);
  129. protected
  130. procedure SetTimerInterval(const Value: Integer);
  131. {$IFDEF VER320_up}
  132. procedure DoResized; override;
  133. {$ELSE}
  134. procedure Resize; override;
  135. {$ENDIF}
  136. procedure DoPageChange(NewPage, OldPage: Integer);
  137. procedure DoTap(Sender: TObject; const Point: TPointF);
  138. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Single); override;
  139. procedure MouseMove(Shift: TShiftState; X, Y: Single); override;
  140. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Single); override;
  141. procedure AddImage(const Value: string; Image: TImageView);
  142. procedure AddPage(const Value: string; Page: TControl);
  143. procedure PrepareSlide(DeltaX: Single); overload;
  144. procedure PrepareSlide(IsIn: Boolean); overload;
  145. public
  146. constructor Create(AOwner: TComponent); override;
  147. destructor Destroy; override;
  148. procedure SetPage(Index: Integer; AImage: TImageView);
  149. procedure Add(Bitmap: TBitmap); overload; //add bitmap
  150. procedure Add(Value: string; Bitmap: TBitmap); overload; //add bitmap and value
  151. procedure Add(Value: string; Bitmap: TStream); overload; //add bitmap stream and value
  152. procedure Clear; //Page Clear;
  153. procedure Prev; //Previous Page
  154. procedure Next; //Next Page
  155. property Datas[Index: Integer]: string read GetDatas write SetDatas; //Page value(ex 0page = Datas[0])
  156. property IsCanDrag: Boolean read FIsCanDrag write FIsCanDrag default True;
  157. published
  158. property Align;
  159. property Height;
  160. property Position;
  161. property Width;
  162. property ActivePage: Integer read FActivePage write SetActivePage; //page move
  163. property AnimateDuration: Single read GetAnimateDuration write SetAnimateDuration;
  164. property AutoSlider: Boolean read FAutoSlider write SetAutoSlider; //auto slider property
  165. property DotActiveColor: TAlphaColor read GetDotActiveColor write SetDotActiveColor;
  166. property DotInActiveColor: TAlphaColor read GetDotInActiveColor write SetDotInActiveColor;
  167. property DotsVisible: Boolean read GetDotsVisible write SetDotsVisible;
  168. property PageCount: Integer read GetPageCount write SetPageCount;
  169. property TimerInterval: Integer read GetTimerInterval write SetTimerInterval; //auto slider timer
  170. property OnCanDragBegin: TCanBeginDragEvent read FOnCanDragBegin write FOnCanDragBegin;
  171. property OnItemClick: TNotifyEvent read FOnItemClick write FOnItemClick; //page click event(use Desktop)
  172. property OnItemTap: TTapEvent read FOnItemTap write FOnItemTap; //page tab event(use Mobile, Pad)
  173. property OnPageChange: TPageChangeEvent read FOnPageChange write FOnPageChange;
  174. property OnPageAnimationFinish: TPageAnimationFinishEvent read FOnPageAnimationFinish write FOnPageAnimationFinish;
  175. end;
  176. implementation
  177. type
  178. TMyAnimation = class(TAnimation)
  179. protected
  180. procedure ProcessAnimation; override;
  181. end;
  182. { TFMXImageSlider }
  183. procedure TFMXImageSlider.Add(Bitmap: TBitmap);
  184. begin
  185. Add('', Bitmap);
  186. end;
  187. procedure TFMXImageSlider.Add(Value: String; Bitmap: TBitmap);
  188. var
  189. Img : TImageView;
  190. begin
  191. Img := TImageView.Create(Self);
  192. Img.Image.SetBitmap(TViewState.None, Bitmap);
  193. AddImage(Value, Img);
  194. end;
  195. procedure TFMXImageSlider.Add(Value: String; Bitmap: TStream);
  196. var
  197. Img : TImageView;
  198. Bmp: TBitmap;
  199. begin
  200. Img := TImageView.Create(Self);
  201. Bmp := TBitmap.Create;
  202. try
  203. Bmp.LoadFromStream(Bitmap);
  204. Img.Image.SetBitmap(TViewState.None, Bmp);
  205. finally
  206. FreeAndNil(Bmp);
  207. end;
  208. AddImage(Value, Img);
  209. end;
  210. procedure TFMXImageSlider.AddImage(const Value: string; Image: TImageView);
  211. var
  212. Page: TLayout;
  213. begin
  214. Page := TLayout.Create(Self);
  215. Image.Stored := False;
  216. Image.ScaleType := TImageScaleType.CenterCrop;
  217. Image.Parent := Page;
  218. Image.HitTest := False;
  219. Image.Align := TAlignLayout.Client;
  220. AddPage(Value, Page);
  221. end;
  222. procedure TFMXImageSlider.AddPage(const Value: string; Page: TControl);
  223. begin
  224. Page.Parent := FContainer;
  225. Page.SetBounds(0,0, FContainer.Width, FContainer.Height);
  226. Page.Stored := False;
  227. Page.Visible := False;
  228. Page.TagString := Value;
  229. Page.Tag := FPages.Add(Page);
  230. FDots.DotCount := PageCount;
  231. end;
  232. procedure TFMXImageSlider.Clear;
  233. var
  234. I: Integer;
  235. begin
  236. for I := FPages.Count-1 downto 0 do
  237. begin
  238. FPages[I].DisposeOf;
  239. end;
  240. FPages.Clear;
  241. ActivePage := -1;
  242. FDots.DotCount := PageCount;
  243. end;
  244. constructor TFMXImageSlider.Create(AOwner: TComponent);
  245. begin
  246. inherited;
  247. FContainer := TControl.Create(Self);
  248. FContainer.Align := TAlignLayout.Client;
  249. FContainer.Stored := False;
  250. FContainer.HitTest := False;
  251. FContainer.ClipChildren := True;
  252. FContainer.Parent := Self;
  253. FDots := TSliderDots.Create(Self);
  254. FDots.Stored := False;
  255. FDots.SetBounds(0, FContainer.Height - FDots.Height, FContainer.Width, FDots.Height);
  256. FDots.Parent := Self;
  257. FTimer := TTimer.Create(Self);
  258. FTimer.Interval := 1000 * 5;
  259. FTimer.Enabled := False;
  260. FTimer.OnTimer := OnTimer;
  261. FAutoSlider := False;
  262. FAnimation := TMyAnimation.Create(Self);
  263. FAnimation.Stored := False;
  264. FAnimation.Interpolation := TInterpolationType.Quintic;
  265. FAnimation.Parent := Self;
  266. FAnimation.Duration := 0.2;
  267. FAnimation.OnProcess := AnimationProcess;
  268. FAnimation.OnFinish := AnimationFinished;
  269. FPages := TList<TControl>.Create;
  270. HitTest := True;
  271. FActivePage := -1;
  272. FStartDrag := False;
  273. AutoCapture := True;
  274. FIsCanDrag := True;
  275. end;
  276. destructor TFMXImageSlider.Destroy;
  277. begin
  278. FPages.Free;
  279. inherited;
  280. end;
  281. procedure TFMXImageSlider.DoPageChange(NewPage, OldPage: Integer);
  282. begin
  283. if Assigned(FOnPageChange) then
  284. FOnPageChange(Self, NewPage, OldPage);
  285. end;
  286. procedure TFMXImageSlider.DoTap(Sender: TObject; const Point: TPointF);
  287. begin
  288. if Assigned(FOnItemTap) then FOnItemTap(Sender, Point);
  289. end;
  290. function TFMXImageSlider.GetAnimateDuration: Single;
  291. begin
  292. Result := FAnimation.Duration;
  293. end;
  294. function TFMXImageSlider.GetDatas(Index: Integer): string;
  295. begin
  296. Result := FPages[Index].TagString;
  297. end;
  298. function TFMXImageSlider.GetDotActiveColor: TAlphaColor;
  299. begin
  300. Result := FDots.ActiveColor;
  301. end;
  302. function TFMXImageSlider.GetDotInActiveColor: TAlphaColor;
  303. begin
  304. Result := FDots.InActiveColor;
  305. end;
  306. function TFMXImageSlider.GetDotsVisible: Boolean;
  307. begin
  308. Result := FDots.Visible;
  309. end;
  310. function TFMXImageSlider.GetPageCount: Integer;
  311. begin
  312. Result := FPages.Count;
  313. end;
  314. function TFMXImageSlider.GetTimerInterval: Integer;
  315. begin
  316. Result := FTimer.Interval;
  317. end;
  318. procedure TFMXImageSlider.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Single);
  319. begin
  320. inherited;
  321. FIsTimer := FTimer.Enabled;
  322. if FIsTimer then
  323. FTimer.Enabled := False;
  324. FIsMove := False;
  325. if IsCanDrag and (PageCount > 0) and (Button = TMouseButton.mbLeft) then
  326. begin
  327. FStartDrag := True;
  328. FBeforeDrag := True;
  329. FDownPos := PointF(X, Y);
  330. FDownIndex := FActivePage;
  331. end;
  332. end;
  333. procedure TFMXImageSlider.MouseMove(Shift: TShiftState; X, Y: Single);
  334. var
  335. DeltaX: Single;
  336. begin
  337. inherited;
  338. if FStartDrag then
  339. begin
  340. if FBeforeDrag and not SetDragBegin then
  341. exit;
  342. if Abs(FDownPos.X - X) > 5 then
  343. FIsMove := True;
  344. DeltaX := X - FDownPos.X;
  345. PrepareSlide(DeltaX);
  346. end;
  347. end;
  348. procedure TFMXImageSlider.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Single);
  349. var
  350. DeltaX: Single;
  351. PrevPage: Integer;
  352. begin
  353. inherited;
  354. if (not FIsMove) and FStartDrag then
  355. begin
  356. if FIsTimer then
  357. FTimer.Enabled := True;
  358. FStartDrag := False;
  359. if Assigned(FOnItemClick) then
  360. FOnItemClick(FPages[Self.ActivePage]);
  361. if Assigned(FOnItemTap) then
  362. FOnItemTap(FPages[Self.ActivePage], PointF(X, Y));
  363. Exit;
  364. end;
  365. if FStartDrag then
  366. begin
  367. FStartDrag := False;
  368. DeltaX := X - FDownPos.X;
  369. if (Abs(DeltaX) > Width * 0.4) and (PageCount > 0) then
  370. begin
  371. if (DeltaX > 0) then
  372. begin
  373. PrevPage := FActivePage;
  374. FActivePage := (FActivePage + PageCount - 1) mod PageCount;
  375. end
  376. else
  377. begin
  378. PrevPage := FActivePage;
  379. FActivePage := (FActivePage + 1) mod PageCount;
  380. end;
  381. DoPageChange(FActivePage, PrevPage);
  382. MoveToActivePage(DeltaX < 0);
  383. end
  384. else
  385. begin
  386. MoveToActivePage(DeltaX > 0);
  387. end;
  388. if FIsTimer then
  389. FTimer.Enabled := True;
  390. end;
  391. end;
  392. procedure TFMXImageSlider.MoveToActivePage(IsIn: Boolean);
  393. begin
  394. PrepareSlide(IsIn);
  395. FAnimation.Start;
  396. end;
  397. procedure TFMXImageSlider.Next;
  398. var
  399. PrevPage: Integer;
  400. begin
  401. if (PageCount < 2) or (FAnimation.Running) then Exit;
  402. PrevPage := FActivePage;
  403. FActivePage := (FActivePage + 1) mod PageCount;
  404. DoPageChange(FActivePage, PrevPage);
  405. MoveToActivePage(True);
  406. end;
  407. procedure TFMXImageSlider.OnTimer(Sender: TObject);
  408. begin
  409. Next;
  410. end;
  411. procedure TFMXImageSlider.PrepareSlide(DeltaX: Single);
  412. var
  413. Layout1, Layout2: TControl;
  414. Index2: Integer;
  415. begin
  416. Layout1 := FPages[FActivePage];
  417. Layout1.Position.X := DeltaX;
  418. if PageCount > 0 then
  419. begin
  420. if DeltaX > 0 then
  421. // Find the left page
  422. Index2 := (FActivePage + PageCount - 1) mod PageCount
  423. else
  424. Index2 := (FActivePage + 1) mod PageCount;
  425. Layout2 := FPages[Index2];
  426. Layout2.Visible := True;
  427. if DeltaX > 0 then
  428. Layout2.Position.X := Layout1.Position.X - Width
  429. else
  430. Layout2.Position.X := Layout1.BoundsRect.Right;
  431. end;
  432. end;
  433. procedure TFMXImageSlider.PrepareSlide(IsIn: Boolean);
  434. var
  435. Layout1, Layout2: TControl;
  436. Index2: Integer;
  437. X: Single;
  438. begin
  439. FTranstionIsIn := IsIn;
  440. Layout1 := FPages[FActivePage];
  441. if Layout1.Visible then
  442. FTranstionStartX := Layout1.Position.X
  443. else
  444. begin
  445. if IsIn then
  446. FTranstionStartX := Width
  447. else
  448. FTranstionStartX := -Width;
  449. Layout1.SetBounds(FTranstionStartX, 0, Width, Height);
  450. Layout1.Visible := true;
  451. end;
  452. if PageCount > 1 then
  453. begin
  454. if IsIn then
  455. Index2 := (FActivePage + PageCount - 1) mod PageCount
  456. else
  457. Index2 := (FActivePage + 1) mod PageCount;
  458. Layout2 := FPages[Index2];
  459. Layout2.Visible := True;
  460. if IsIn then
  461. X := Layout1.Position.X - Width
  462. else
  463. X := Layout1.BoundsRect.Right;
  464. Layout2.SetBounds(X, 0, Width, Height);
  465. SetLength(FTransitionLayouts, 2);
  466. FTransitionLayouts[0] := Layout1;
  467. FTransitionLayouts[1] := Layout2;
  468. end
  469. else
  470. begin
  471. SetLength(FTransitionLayouts, 1);
  472. FTransitionLayouts[0] := Layout1;
  473. end;
  474. end;
  475. procedure TFMXImageSlider.Prev;
  476. var
  477. PrevPage: Integer;
  478. begin
  479. if (PageCount < 2) or (FAnimation.Running) then Exit;
  480. PrevPage := FActivePage;
  481. FActivePage := (FActivePage - 1 + PageCount) mod PageCount;
  482. DoPageChange(FActivePage, PrevPage);
  483. MoveToActivePage(False);
  484. end;
  485. {$IFDEF VER320_up}
  486. procedure TFMXImageSlider.DoResized;
  487. {$ELSE}
  488. procedure TFMXImageSlider.Resize;
  489. {$ENDIF}
  490. var
  491. I: Integer;
  492. begin
  493. inherited;
  494. for I := 0 to FPages.Count - 1 do
  495. begin
  496. FPages[I].Width := FContainer.Width;
  497. FPages[I].Height := FContainer.Height;
  498. end;
  499. FDots.SetBounds(0, FContainer.Height - FDots.Height, FContainer.Width, FDots.Height);
  500. end;
  501. procedure TFMXImageSlider.SetActivePage(const Value: Integer);
  502. var
  503. IsIn: Boolean;
  504. PrevPage, Delta: Integer;
  505. begin
  506. if (Value < 0) or (Value > FPages.Count - 1) then // check if value valid
  507. exit;
  508. if FActivePage <> Value then
  509. begin
  510. PrevPage := FActivePage;
  511. if FActivePage = -1 then
  512. begin
  513. FActivePage := Value;
  514. FPages[FActivePage].SetBounds(0,0,Width,Height);
  515. FPages[FActivePage].Visible := True;
  516. DoPageChange(FActivePage, PrevPage);
  517. FDots.ActiveIndex := FActivePage;
  518. end
  519. else
  520. begin
  521. Delta := Abs(FActivePage - Value);
  522. // if current active page not neighbor of new active page, hide current page
  523. if (Delta <> 1) and (Delta <> (PageCount-1)) then
  524. FPages[FActivePage].Visible := False;
  525. IsIn := FActivePage < Value;
  526. FActivePage := Value; // set FActivePage
  527. DoPageChange(FActivePage, PrevPage);
  528. MoveToActivePage(IsIn);
  529. end;
  530. end;
  531. end;
  532. procedure TFMXImageSlider.SetAnimateDuration(const Value: Single);
  533. begin
  534. FAnimation.Duration := Value;
  535. end;
  536. procedure TFMXImageSlider.AnimationFinished(Sender: TObject);
  537. begin
  538. if FTransitionLayouts[0].Tag = FActivePage then
  539. begin
  540. if Length(FTransitionLayouts) = 2 then
  541. FTransitionLayouts[1].Visible := False;
  542. end
  543. else
  544. begin
  545. FTransitionLayouts[0].Visible := False;
  546. end;
  547. If Assigned(FOnPageAnimationFinish) then
  548. FOnPageAnimationFinish(Self, FActivePage);
  549. FBeforeDrag := True;
  550. FDots.ActiveIndex := FActivePage;
  551. end;
  552. procedure TFMXImageSlider.AnimationProcess(Sender: TObject);
  553. var
  554. Start, Stop: Single;
  555. begin
  556. Start := FTranstionStartX;
  557. Stop := 0;
  558. FTransitionLayouts[0].Position.X :=
  559. InterpolateSingle(Start, Stop, FAnimation.NormalizedTime);
  560. if Length(FTransitionLayouts) = 2 then
  561. begin
  562. if FTranstionIsIn then
  563. FTransitionLayouts[1].Position.X := FTransitionLayouts[0].Position.X - Width
  564. else
  565. FTransitionLayouts[1].Position.X := FTransitionLayouts[0].BoundsRect.Right;
  566. end;
  567. end;
  568. function TFMXImageSlider.SetDragBegin: Boolean;
  569. var
  570. CanBeginDrag: Boolean;
  571. begin
  572. Result := True;
  573. if Assigned(FOnCanDragBegin) then
  574. begin
  575. FBeforeDrag := False;
  576. FOnCanDragBegin(Self, CanBeginDrag);
  577. Result := CanBeginDrag;
  578. end;
  579. end;
  580. procedure TFMXImageSlider.SetAutoSlider(const Value: Boolean);
  581. begin
  582. FAutoSlider := Value;
  583. FTimer.Enabled := Value;
  584. end;
  585. procedure TFMXImageSlider.SetDatas(Index: Integer; const Value: string);
  586. begin
  587. FPages[Index].TagString := Value;
  588. end;
  589. procedure TFMXImageSlider.SetDotActiveColor(const Value: TAlphaColor);
  590. begin
  591. FDots.ActiveColor := Value;
  592. end;
  593. procedure TFMXImageSlider.SetDotInActiveColor(const Value: TAlphaColor);
  594. begin
  595. FDots.InActiveColor := Value;
  596. end;
  597. procedure TFMXImageSlider.SetDotsVisible(const Value: Boolean);
  598. begin
  599. FDots.Visible := Value;
  600. end;
  601. procedure TFMXImageSlider.SetPage(Index: Integer; AImage: TImageView);
  602. begin
  603. if (Index >= 0) and (Index < PageCount) then
  604. begin
  605. AImage.HitTest := False;
  606. AImage.Parent := FPages[Index];
  607. AImage.Align := TAlignLayout.Client;
  608. end;
  609. end;
  610. procedure TFMXImageSlider.SetPageCount(const Value: Integer);
  611. var
  612. OldCount: Integer;
  613. I: Integer;
  614. L: TControl;
  615. begin
  616. if Value <> PageCount then
  617. begin
  618. OldCount := PageCount;
  619. if OldCount < Value then
  620. begin
  621. for I := OldCount + 1 to Value do
  622. begin
  623. AddPage('', TLayout.Create(Self));
  624. end;
  625. end
  626. else if OldCount > Value then
  627. begin
  628. for I := OldCount - 1 downto Value do
  629. begin
  630. L := FPages[I];
  631. L.DisposeOf;
  632. end;
  633. FPages.Count := Value;
  634. end;
  635. if Value > 0 then
  636. begin
  637. ActivePage := 0;
  638. end
  639. else
  640. begin
  641. ActivePage := -1;
  642. end;
  643. end;
  644. end;
  645. procedure TFMXImageSlider.SetTimerInterval(const Value: Integer);
  646. begin
  647. FTimer.Interval := Value;
  648. end;
  649. { TMyAnimation }
  650. procedure TMyAnimation.ProcessAnimation;
  651. begin
  652. end;
  653. { TSliderDots }
  654. constructor TSliderDots.Create(AOwner: TComponent);
  655. begin
  656. inherited;
  657. FDotSize := 12;
  658. FActiveIndex := -1;
  659. FDotContainer := TLayout.Create(Self);
  660. FDotContainer.Stored := False;
  661. FDotContainer.Height := FDotSize;
  662. FDotContainer.HitTest := False;
  663. FDotContainer.Parent := Self;
  664. FInActiveColor := $FFDDDDDD;
  665. FActiveColor := $FF00B4FF;
  666. HitTest := False;
  667. Height := FDotSize * 2;
  668. end;
  669. procedure TSliderDots.CreateDotShape;
  670. var
  671. Dot: TShape;
  672. X, W: Single;
  673. B: TRectF;
  674. begin
  675. X := DotCount * DotSize * 2;
  676. Dot := TCircle.Create(Self);
  677. Dot.HitTest := False;
  678. Dot.SetBounds(X, 0, DotSize, DotSize);
  679. Dot.Stroke.Kind := TBrushKind.None;
  680. Dot.Fill.Kind := TBrushKind.Solid;
  681. Dot.Fill.Color := FInActiveColor;
  682. Dot.Parent := FDotContainer;
  683. X := (Self.Width - FDotContainer.Width) / 2;
  684. W := (DotCount * 2 - 1) * DotSize;
  685. B := TRectF.Create(X, 0, X + W, DotSize);
  686. if Assigned(Scene) then //fixed by kngstr
  687. B := B.SnapToPixel(Scene.GetSceneScale, False);
  688. FDotContainer.BoundsRect := B;
  689. end;
  690. {$IFDEF VER320_up}
  691. procedure TSliderDots.DoResized;
  692. {$ELSE}
  693. procedure TSliderDots.Resize;
  694. {$ENDIF}
  695. var
  696. X, W: Single;
  697. B: TRectF;
  698. begin
  699. inherited;
  700. X := (Self.Width - FDotContainer.Width) / 2;
  701. W := (DotCount * 2 - 1) * DotSize;
  702. B := TRectF.Create(X, 0, X + W, DotSize);
  703. // B := B.SnapToPixel(Scene.GetSceneScale, False);
  704. FDotContainer.BoundsRect := B;
  705. end;
  706. function TSliderDots.GetDot(Index: Integer): TControl;
  707. begin
  708. Result := TControl(FDotContainer.Children[Index]);
  709. end;
  710. function TSliderDots.GetDotCount: Integer;
  711. begin
  712. Result := FDotContainer.ChildrenCount;
  713. end;
  714. procedure TSliderDots.HitTestChanged;
  715. begin
  716. inherited;
  717. end;
  718. procedure TSliderDots.SetActiveColor(const Value: TAlphaColor);
  719. begin
  720. if FActiveColor <> Value then
  721. begin
  722. FActiveColor := Value;
  723. if (FActiveIndex >= 0) and (FActiveIndex < GetDotCount) then
  724. begin
  725. (GetDot(FActiveIndex) as TShape).Fill.Color := FActiveColor;
  726. end;
  727. end;
  728. end;
  729. procedure TSliderDots.SetActiveIndex(const Value: Integer);
  730. begin
  731. if FActiveIndex <> Value then
  732. begin
  733. if (FActiveIndex >= 0) and (FActiveIndex < DotCount) then
  734. begin
  735. (GetDot(FActiveIndex) as TShape).Fill.Color := FInActiveColor;
  736. end;
  737. FActiveIndex := Value;
  738. if (FActiveIndex >= 0) and (FActiveIndex < DotCount) then
  739. begin
  740. (GetDot(FActiveIndex) as TShape).Fill.Color := FActiveColor;
  741. end;
  742. end;
  743. end;
  744. procedure TSliderDots.SetDotCount(const Value: Integer);
  745. var
  746. OldCount: Integer;
  747. I: Integer;
  748. Dot: TFMXObject;
  749. begin
  750. if Value <> DotCount then
  751. begin
  752. OldCount := DotCount;
  753. if OldCount < Value then
  754. begin
  755. for I := OldCount + 1 to Value do
  756. begin
  757. CreateDotShape;
  758. end;
  759. end
  760. else
  761. begin
  762. for I := OldCount - 1 downto Value do
  763. begin
  764. Dot := FDotContainer.Children[I];
  765. Dot.DisposeOf;
  766. end;
  767. end;
  768. end;
  769. end;
  770. procedure TSliderDots.SetDotSize(const Value: Single);
  771. begin
  772. if FDotSize <> Value then
  773. begin
  774. FDotSize := Value;
  775. FDotContainer.Height := FDotSize;
  776. Height := FDotSize * 3;
  777. end;
  778. end;
  779. procedure TSliderDots.SetInActiveColor(const Value: TAlphaColor);
  780. var
  781. I: Integer;
  782. Dot: TShape;
  783. begin
  784. if FInActiveColor <> Value then
  785. begin
  786. FInActiveColor := Value;
  787. for I := 0 to DotCount-1 do
  788. begin
  789. if I <> FActiveIndex then
  790. begin
  791. Dot := GetDot(I) as TShape;
  792. Dot.Fill.Color := FInActiveColor;
  793. end;
  794. end;
  795. end;
  796. end;
  797. end.