19
19
// 4. add TimerInterval to control AutoSlider interval
20
20
// 5. use ActivePage property move page, ex)ActivePage := 1
21
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
22
26
23
27
unit FMX.ImageSlider;
24
28
@@ -38,26 +42,35 @@ interface
38
42
FMX.ComponentsCommon;
39
43
40
44
type
45
+ TPageChangeEvent = procedure(Sender: TObject; NewPage, OldPage: Integer) of object ;
46
+ TPageAnimationFinishEvent = procedure(Sender: TObject; NewPage, OldPage: Integer) of object ;
47
+ TCanBeginDragEvent = procedure(Sender: TObject; var CanBegin: Boolean) of object ;
41
48
42
49
[ComponentPlatformsAttribute(TFMXPlatforms)]
43
50
TFMXImageSlider = class (TLayout)
44
51
private
45
- FIsTimer : Boolean;
46
- FAutoSlider : Boolean;
47
- FTimer : TTimer;
48
- FContainer : TLayout;
49
- FPages : TList<TLayout>;
50
- FActivePage : Integer;
51
- FIsMove : Boolean;
52
- FStartDrag : Boolean;
53
- FDownPos : TPointF;
54
- FDownIndex : Integer;
55
- FAnimation : TFloatAnimation;
56
- FOnItemTap : TTapEvent;
57
- FOnItemClick : TNotifyEvent;
58
- FOnPageChanged: TNotifyEvent;
52
+ FIsTimer: Boolean;
53
+ FAutoSlider: Boolean;
54
+ FTimer: TTimer;
55
+ FContainer: TLayout;
56
+ FPages: TList<TLayout>;
57
+ FActivePage: Integer;
58
+ FIsMove: Boolean;
59
+ FStartDrag: Boolean;
60
+ FBeforeDrag: Boolean;
61
+ FDownPos: TPointF;
62
+ FDownIndex: Integer;
63
+ FPreviousPage: Integer;
64
+ FAnimation: TFloatAnimation;
65
+ FOnPageAnimationFinish: TPageAnimationFinishEvent;
66
+ FOnCanDragBegin: TCanBeginDragEvent;
67
+ FOnItemTap: TTapEvent;
68
+ FOnItemClick: TNotifyEvent;
69
+ FOnPageChange: TPageChangeEvent;
70
+ procedure DoPageChange (NewPage, OldPage: Integer);
59
71
procedure MoveToActivePage (IsIn: Boolean = True);
60
72
procedure OnTimer (Sender: TObject);
73
+ procedure AnimationFinished (Sender:TObject);
61
74
function GetDatas (Index: Integer): string;
62
75
function GetPageCount : Integer;
63
76
function GetTimerInterval : Integer;
@@ -66,6 +79,7 @@ TFMXImageSlider = class(TLayout)
66
79
procedure SetAutoSlider (const Value : Boolean);
67
80
procedure SetPageCount (const Value : Integer);
68
81
procedure SetDatas (Index: Integer; const Value : string);
82
+ function SetDragBegin : Boolean;
69
83
protected
70
84
procedure SetTimerInterval (const Value : Integer);
71
85
procedure Resize ; override;
@@ -89,13 +103,15 @@ TFMXImageSlider = class(TLayout)
89
103
property Height;
90
104
property Position;
91
105
property Width;
92
- property ActivePage : Integer read FActivePage write SetActivePage; // page move
93
- property AutoSlider : Boolean read FAutoSlider write SetAutoSlider; // auto slider property
94
- property PageCount : Integer read GetPageCount write SetPageCount;
95
- property TimerInterval : Integer read GetTimerInterval write SetTimerInterval; // auto slider timer
96
- property OnPageChanged : TNotifyEvent read FOnPageChanged write FOnPageChanged;
97
- property OnItemClick : TNotifyEvent read FOnItemClick write FOnItemClick; // page click event(use Desktop)
98
- property OnItemTap : TTapEvent read FOnItemTap write FOnItemTap; // page tab event(use Mobile, Pad)
106
+ property ActivePage: Integer read FActivePage write SetActivePage; // page move
107
+ property AutoSlider: Boolean read FAutoSlider write SetAutoSlider; // auto slider property
108
+ property PageCount: Integer read GetPageCount write SetPageCount;
109
+ property TimerInterval: Integer read GetTimerInterval write SetTimerInterval; // auto slider timer
110
+ property OnCanDragBegin: TCanBeginDragEvent read FOnCanDragBegin write FOnCanDragBegin;
111
+ property OnItemClick: TNotifyEvent read FOnItemClick write FOnItemClick; // page click event(use Desktop)
112
+ property OnItemTap: TTapEvent read FOnItemTap write FOnItemTap; // page tab event(use Mobile, Pad)
113
+ property OnPageChange: TPageChangeEvent read FOnPageChange write FOnPageChange;
114
+ property OnPageAnimationFinish: TPageAnimationFinishEvent read FOnPageAnimationFinish write FOnPageAnimationFinish;
99
115
end ;
100
116
101
117
implementation
@@ -118,15 +134,14 @@ procedure TFMXImageSlider.Add(Value: String; Bitmap: TBitmap);
118
134
Item.Height := Self.Height;
119
135
Item.Stored := False;
120
136
Item.Position.X := FPages.Count * Width;
121
- Item.Index := FPages.Add(Item);
137
+ Item.Tag := FPages.Add(Item);
122
138
Item.OnTap := DoTab;
123
139
Img := TImage.Create(Item);
124
140
Img.Parent := Item;
125
141
Img.HitTest := False;
126
142
Img.Align := TAlignLayout.Client;
127
143
Img.Bitmap.Assign(Bitmap);
128
144
Item.TagString := Value ;
129
- // ActivePage := 0;
130
145
FContainer.Width := FPages.Count * Width;
131
146
FContainer.Position.X := 0 ;
132
147
if FActivePage = -1 then
@@ -144,15 +159,14 @@ procedure TFMXImageSlider.Add(Value: String; Bitmap: TStream);
144
159
Item.Height := Self.Height;
145
160
Item.Stored := False;
146
161
Item.Position.X := FPages.Count * Width;
147
- Item.Index := FPages.Add(Item);
162
+ Item.Tag := FPages.Add(Item);
148
163
Item.OnTap := DoTab;
149
164
Img := TImage.Create(Item);
150
165
Img.Parent := Item;
151
166
Img.HitTest := False;
152
167
Img.Align := TAlignLayout.Client;
153
168
Img.Bitmap.LoadFromStream(Bitmap);
154
169
Item.TagString := Value ;
155
- // ActivePage := 0;
156
170
FContainer.Width := FPages.Count * Width;
157
171
FContainer.Position.X := 0 ;
158
172
if FActivePage = -1 then
@@ -189,11 +203,13 @@ constructor TFMXImageSlider.Create(AOwner: TComponent);
189
203
FAnimation.PropertyName := ' Position.X' ;
190
204
FAnimation.Parent := FContainer;
191
205
FAnimation.Duration := 0.1 ;
192
- FPages := TList<TLayout>.Create;
193
- HitTest := True;
194
- ActivePage := -1 ;
195
- FStartDrag := False;
196
- AutoCapture := True;
206
+ FAnimation.OnFinish := AnimationFinished;
207
+ FPages := TList<TLayout>.Create;
208
+ HitTest := True;
209
+ ActivePage := -1 ;
210
+ FPreviousPage := -1 ;
211
+ FStartDrag := False;
212
+ AutoCapture := True;
197
213
end ;
198
214
199
215
destructor TFMXImageSlider.Destroy;
@@ -202,6 +218,12 @@ destructor TFMXImageSlider.Destroy;
202
218
inherited ;
203
219
end ;
204
220
221
+ procedure TFMXImageSlider.DoPageChange (NewPage, OldPage: Integer);
222
+ begin
223
+ if Assigned(FOnPageChange) then
224
+ FOnPageChange(Self, NewPage, OldPage);
225
+ end ;
226
+
205
227
procedure TFMXImageSlider.DoTab (Sender: TObject; const Point: TPointF);
206
228
begin
207
229
if Assigned(FOnItemTap) then FOnItemTap(Sender, Point);
@@ -225,12 +247,14 @@ function TFMXImageSlider.GetTimerInterval: Integer;
225
247
procedure TFMXImageSlider.MouseDown (Button: TMouseButton; Shift: TShiftState; X, Y: Single);
226
248
begin
227
249
inherited ;
228
- FIsTimer := FTimer.Enabled;
229
- if FIsTimer then FTimer.Enabled := False;
230
- FIsMove := False;
250
+ FIsTimer := FTimer.Enabled;
251
+ if FIsTimer then
252
+ FTimer.Enabled := False;
253
+ FIsMove := False;
231
254
if (PageCount > 0 ) and (Button = TMouseButton.mbLeft) then
232
255
begin
233
256
FStartDrag := True;
257
+ FBeforeDrag := True;
234
258
FDownPos := PointF(X, Y);
235
259
FDownIndex := FActivePage;
236
260
end ;
@@ -243,7 +267,10 @@ procedure TFMXImageSlider.MouseMove(Shift: TShiftState; X, Y: Single);
243
267
inherited ;
244
268
if FStartDrag then
245
269
begin
246
- if Abs(FDownPos.X - X) > 5 then FIsMove := True;
270
+ if FBeforeDrag and not SetDragBegin then
271
+ exit;
272
+ if Abs(FDownPos.X - X) > 5 then
273
+ FIsMove := True;
247
274
DeltaX := X - FDownPos.X;
248
275
NewX := -FDownIndex * Width + DeltaX;
249
276
FContainer.Position.X := NewX;
@@ -257,29 +284,43 @@ procedure TFMXImageSlider.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y
257
284
inherited ;
258
285
if (not FIsMove) and FStartDrag then
259
286
begin
260
- if FIsTimer then FTimer.Enabled := True;
287
+ if FIsTimer then
288
+ FTimer.Enabled := True;
261
289
FStartDrag := False;
262
- if Assigned(FOnItemClick) then FOnItemClick(FPages[Self.ActivePage]);
263
- if Assigned(FOnItemTap) then FOnItemTap(FPages[Self.ActivePage], PointF(X, Y));
290
+ if Assigned(FOnItemClick) then
291
+ FOnItemClick(FPages[Self.ActivePage]);
292
+ if Assigned(FOnItemTap) then
293
+ FOnItemTap(FPages[Self.ActivePage], PointF(X, Y));
264
294
Exit;
265
295
end ;
266
296
if FStartDrag then
267
297
begin
268
298
FStartDrag := False;
269
299
DeltaX := X - FDownPos.X;
270
- if (DeltaX > Width * 0.4 ) then
271
- begin
272
- if FActivePage > 0 then
273
- FActivePage := FActivePage - 1 ;
274
- end
275
- else if DeltaX < (-Width * 0.4 ) then
300
+ if Abs(DeltaX) > Width * 0.4 then
276
301
begin
277
- if FActivePage < PageCount - 1 then
278
- FActivePage := FActivePage + 1 ;
302
+ if (DeltaX > 0 ) then
303
+ begin
304
+ if FActivePage > 0 then
305
+ begin
306
+ FPreviousPage := FActivePage;
307
+ FActivePage := FActivePage - 1 ;
308
+ DoPageChange(FActivePage, FPreviousPage);
309
+ end ;
310
+ end
311
+ else if (DeltaX < 0 ) then
312
+ begin
313
+ if FActivePage < PageCount - 1 then
314
+ begin
315
+ FPreviousPage := FActivePage;
316
+ FActivePage := FActivePage + 1 ;
317
+ DoPageChange(FActivePage, FPreviousPage);
318
+ end ;
319
+ end ;
279
320
end ;
280
321
MoveToActivePage(DeltaX < 0 );
281
- if FIsTimer then FTimer.Enabled := True;
282
- if Assigned(FOnPageChanged) then Self.FOnPageChanged(Self) ;
322
+ if FIsTimer then
323
+ FTimer.Enabled := True ;
283
324
end ;
284
325
end ;
285
326
@@ -298,9 +339,10 @@ procedure TFMXImageSlider.MoveToActivePage(IsIn: Boolean);
298
339
procedure TFMXImageSlider.Next ;
299
340
begin
300
341
if FActivePage = FPages.Count - 1 then Exit;
342
+ FPreviousPage := FActivePage;
301
343
FActivePage := FActivePage + 1 ;
344
+ DoPageChange(FActivePage, FPreviousPage);
302
345
MoveToActivePage(True);
303
- if Assigned(FOnPageChanged) then Self.FOnPageChanged(Self);
304
346
end ;
305
347
306
348
procedure TFMXImageSlider.OnTimer (Sender: TObject);
@@ -312,9 +354,10 @@ procedure TFMXImageSlider.OnTimer(Sender: TObject);
312
354
procedure TFMXImageSlider.Prev ;
313
355
begin
314
356
if FActivePage = 0 then Exit;
357
+ FPreviousPage := FActivePage;
315
358
FActivePage := FActivePage - 1 ;
359
+ DoPageChange(FActivePage, FPreviousPage);
316
360
MoveToActivePage(False);
317
- if Assigned(FOnPageChanged) then Self.FOnPageChanged(Self);
318
361
end ;
319
362
320
363
procedure TFMXImageSlider.Resize ;
@@ -331,23 +374,43 @@ procedure TFMXImageSlider.Resize;
331
374
FPages[I].Width := Width;
332
375
FPages[I].Height := Height;
333
376
FPages[I].Position.X := I * Width;
334
- FPages[i ].RecalcSize;
377
+ FPages[I ].RecalcSize;
335
378
end ;
336
379
end ;
337
380
338
381
procedure TFMXImageSlider.SetActivePage (const Value : Integer);
339
382
var
340
383
IsIn: Boolean;
341
384
begin
385
+ if (Value < 0 ) or (Value > FPages.Count - 1 ) then // check if value valid
386
+ exit;
342
387
if FActivePage <> Value then
343
388
begin
344
- if FActivePage = -1 then FContainer.Position.X := 0
345
- else
346
- begin
347
- IsIn := FActivePage < Value ;
348
- FActivePage := Value ;
349
- MoveToActivePage(IsIn);
350
- end ;
389
+ IsIn := FActivePage < Value ;
390
+ FPreviousPage := FActivePage;
391
+ FActivePage := Value ; // set FActivePage
392
+ DoPageChange(FActivePage, FPreviousPage);
393
+ MoveToActivePage(IsIn);
394
+ end ;
395
+ end ;
396
+
397
+ procedure TFMXImageSlider.AnimationFinished (Sender: TObject);
398
+ begin
399
+ If Assigned(FOnPageAnimationFinish) then
400
+ FOnPageAnimationFinish(Self, FActivePage, FPreviousPage);
401
+ FBeforeDrag := True;
402
+ end ;
403
+
404
+ function TFMXImageSlider.SetDragBegin : Boolean;
405
+ var
406
+ CanBeginDrag: Boolean;
407
+ begin
408
+ Result := True;
409
+ if Assigned(FOnCanDragBegin) then
410
+ begin
411
+ FBeforeDrag := False;
412
+ FOnCanDragBegin(Self, CanBeginDrag);
413
+ Result := CanBeginDrag;
351
414
end ;
352
415
end ;
353
416
0 commit comments