Line data Source code
1 : import 'package:flutter/material.dart';
2 : import 'package:flutter/widgets.dart';
3 : import 'package:liquid_swipe/Helpers/Helpers.dart';
4 : import 'package:liquid_swipe/Helpers/LiquidSwipeChildDelegate.dart';
5 : import 'package:liquid_swipe/PageHelpers/LiquidController.dart';
6 : import 'package:liquid_swipe/PageHelpers/page_dragger.dart';
7 : import 'package:liquid_swipe/PageHelpers/page_reveal.dart';
8 : import 'package:liquid_swipe/Provider/LiquidProvider.dart';
9 : import 'package:provider/provider.dart';
10 :
11 : export 'package:liquid_swipe/Helpers/Helpers.dart';
12 : export 'package:liquid_swipe/PageHelpers/LiquidController.dart';
13 :
14 0 : final key = new GlobalKey<_LiquidSwipe>();
15 :
16 : /// Callback to provide the current page Index whenever it changes
17 : ///
18 : /// Returns an [int] value.
19 : ///
20 : /// Simple Usage :
21 : ///
22 : /// Create your own method
23 : ///
24 : /// ```dart
25 : /// pageChangeCallback(int page) {
26 : /// ...performActions
27 : /// }
28 : /// ```
29 : /// add this methods as callback to [LiquidSwipe.onPageChangeCallback]
30 : ///
31 : /// ```dart
32 : /// LiquidSwipe(
33 : /// pages: pages,
34 : /// onPageChangeCallback: pageChangeCallback,
35 : /// ),
36 : /// ```
37 : ///
38 : /// see also : [LiquidController.currentPage]
39 : typedef OnPageChangeCallback = void Function(int activePageIndex);
40 :
41 : /// Callback to provide the current UpdateType
42 : ///
43 : /// Returns an [UpdateType] value.
44 : ///
45 : /// Simple Usage :
46 : ///
47 : /// Create your own method
48 : ///
49 : /// ```dart
50 : /// updateChangeCallback(UpdateType type) {
51 : /// ...performActions
52 : /// }
53 : /// ```
54 : /// add this methods as callback to [LiquidSwipe.currentUpdateTypeCallback]
55 : ///
56 : /// ```dart
57 : /// LiquidSwipe(
58 : /// pages: pages,
59 : /// currentUpdateTypeCallback: updateChangeCallback,
60 : /// ),
61 : /// ```
62 : typedef CurrentUpdateTypeCallback = void Function(UpdateType updateType);
63 :
64 : /// Callback to provide the slidePercentage, both vertical and horizontal
65 : ///
66 : /// Returns two [double] values.
67 : ///
68 : /// Simple Usage :
69 : ///
70 : /// use [LiquidSwipe.slidePercentCallback] for callbacks
71 : ///
72 : /// ```dart
73 : /// LiquidSwipe(
74 : /// pages: pages,
75 : /// slidePercentCallback: (slidePercentHorizontal, slidePercentVertical) => {
76 : /// ...performActions
77 : /// },
78 : /// ),
79 : /// ```
80 : typedef SlidePercentCallback = void Function(
81 : double slidePercentHorizontal, double slidePercentVertical);
82 :
83 : /// LiquidSwipe widget for out of the box Animation between stacked Widgets.
84 : ///
85 : /// For Simple Usage LiquidSwipe just requires List of Widgets and assign it to [LiquidSwipe.pages]
86 : ///
87 : /// Pages can be or should be Containers or SizedBox etc. Please report if doesn't work on some specific type of the Widgets
88 : ///
89 : /// Example :
90 : ///
91 : /// ```dart
92 : /// LiquidSwipe(
93 : /// pages: pages,
94 : /// ),
95 : /// ```
96 : ///
97 : /// All Other parameters are optional and can be neglected, otherwise see documentation related to each of them.
98 : ///
99 : /// An Example of LiquidSwipe with Default values (excluding callbacks) :
100 : ///
101 : /// [LiquidSwipe()]
102 : /// ```dart
103 : /// LiquidSwipe(
104 : /// pages: pages,
105 : /// fullTransitionValue: FULL_TRANSITION_PX,
106 : /// initialPage: 0,
107 : /// enableSlideIcon: false,
108 : /// slideIconWidget: const Icon(Icons.arrow_back_ios),
109 : /// positionSlideIcon: 0.54,
110 : /// enableLoop: true,
111 : /// waveType: WaveType.liquidReveal,
112 : /// liquidController: liquidController,
113 : /// disableUserGesture: false,
114 : /// ignoreUserGestureWhileAnimating: false,
115 : /// ),
116 : /// ```
117 : ///
118 : /// [LiquidSwipe.builder(itemBuilder: itemBuilder, itemCount: itemCount)]
119 : /// ```dart
120 : /// LiquidSwipe.builder(
121 : /// itemCount : data.length,
122 : /// itemBuilder : (context, index) => Container(...),
123 : /// fullTransitionValue: FULL_TRANSITION_PX,
124 : /// initialPage: 0,
125 : /// enableSlideIcon: false,
126 : /// slideIconWidget: const Icon(Icons.arrow_back_ios),
127 : /// positionSlideIcon: 0.54,
128 : /// enableLoop: true,
129 : /// waveType: WaveType.liquidReveal,
130 : /// liquidController: liquidController,
131 : /// disableUserGesture: false,
132 : /// ignoreUserGestureWhileAnimating: false,
133 : /// ),
134 : /// ```
135 : class LiquidSwipe extends StatefulWidget {
136 : /// Required a double value for swipe animation sensitivity
137 : ///
138 : /// Default : 400
139 : ///
140 : /// Lower the value faster the animation
141 : ///
142 : /// 100 would make animation much faster than current
143 : final double fullTransitionValue;
144 :
145 : /// If you want to change the initial page
146 : ///
147 : /// Required a int value which should be greater than or equals to 0 and less then the pages length other wise exception will be thrown.
148 : final int initialPage;
149 :
150 : /// Required a Widget that will be visible only if [enableSlideIcon] is set to true
151 : ///
152 : /// If not provided and [enableSlideIcon] is set [true], `Icon(Icons.arrow_back_ios)` this will be used by default
153 : final Widget? slideIconWidget;
154 :
155 : /// Required a double value ranges from 0.0 - 1.0
156 : ///
157 : /// -1.0 represents the 0% of height of the canvas and 100% for 1.0, similarly 0.0 represents vertical centre
158 : final double positionSlideIcon;
159 :
160 : /// Required a bool value in order to make the swipe in loop mode or not, i.e., to repeat them or not after reaching last page.
161 : final bool enableLoop;
162 :
163 : ///Required a [LiquidController] object for some magic methods
164 : final LiquidController? liquidController;
165 :
166 : ///Type of Wave you want, its a enum, you might have to import helpers.dart
167 : final WaveType waveType;
168 :
169 : ///see [OnPageChangeCallback]
170 : final OnPageChangeCallback? onPageChangeCallback;
171 :
172 : ///see [CurrentUpdateTypeCallback]
173 : final CurrentUpdateTypeCallback? currentUpdateTypeCallback;
174 :
175 : ///see [SlidePercentCallback]
176 : final SlidePercentCallback? slidePercentCallback;
177 :
178 : ///Required a bool value for disabling Fast Animation between pages
179 : ///
180 : /// If true fast swiping is disabled
181 : final bool ignoreUserGestureWhileAnimating;
182 :
183 : ///Required a bool value for disabling the user touch. you can still perform programmatic swipes
184 : ///
185 : ///see also for runtime changes : [LiquidController.shouldDisableGestures]
186 : final bool disableUserGesture;
187 :
188 : ///Required a bool to Enable or Disable the side reveal i.e., this clip area on the right side with 15.0px of reveal.
189 : final bool enableSideReveal;
190 :
191 : /// A Custom child delegate responsible for child creation in case of builder or fetcher in case of List.
192 : ///
193 : /// See also [LiquidSwipeChildDelegate]
194 : final LiquidSwipeChildDelegate liquidSwipeChildDelegate;
195 :
196 : /// Constructor for LiquidSwipe for predefined [pages]
197 : ///Required List of Widgets like Container/SizedBox
198 : ///
199 : /// sample page :
200 : ///
201 : /// ```dart
202 : /// Container(
203 : /// color: Colors.pink,
204 : /// child: Column(
205 : /// crossAxisAlignment: CrossAxisAlignment.center,
206 : /// mainAxisSize: MainAxisSize.max,
207 : /// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
208 : /// children: <Widget>[
209 : /// Image.asset(
210 : /// 'assets/1.png',
211 : /// fit: BoxFit.cover,
212 : /// ),
213 : /// Padding(
214 : /// padding: EdgeInsets.all(20.0),
215 : /// ),
216 : /// Column(
217 : /// children: <Widget>[
218 : /// Text(
219 : /// "Hi",
220 : /// style: MyApp.style,
221 : /// ),
222 : /// Text(
223 : /// "It's Me",
224 : /// style: MyApp.style,
225 : /// ),
226 : /// Text(
227 : /// "Sahdeep",
228 : /// style: MyApp.style,
229 : /// ),
230 : /// ],
231 : /// ),
232 : /// ],
233 : /// ),
234 : /// ),
235 : /// ```
236 : ///
237 : /// You can just create a list using this type of widgets
238 1 : LiquidSwipe({
239 : Key? key,
240 : required List<Widget> pages,
241 : this.fullTransitionValue = FULL_TRANSITION_PX,
242 : this.initialPage = 0,
243 : this.slideIconWidget,
244 : this.positionSlideIcon = 0.8,
245 : this.enableLoop = true,
246 : this.liquidController,
247 : this.waveType = WaveType.liquidReveal,
248 : this.onPageChangeCallback,
249 : this.currentUpdateTypeCallback,
250 : this.slidePercentCallback,
251 : this.ignoreUserGestureWhileAnimating = false,
252 : this.disableUserGesture = false,
253 : this.enableSideReveal = false,
254 3 : }) : assert(initialPage >= 0 && initialPage < pages.length),
255 2 : assert(positionSlideIcon >= 0 && positionSlideIcon <= 1),
256 1 : liquidSwipeChildDelegate = LiquidSwipePagesChildDelegate(pages),
257 1 : super(key: key);
258 :
259 : ///A builder constructor with same fields but with [itemBuilder]
260 : ///Sample itembuilder :
261 : ///
262 : /// itemCount: data.length,
263 : /// itemBuilder: (context, index){
264 : /// return Container(
265 : /// color: data[index].color,
266 : /// child: Column(
267 : /// crossAxisAlignment: CrossAxisAlignment.center,
268 : /// mainAxisSize: MainAxisSize.max,
269 : /// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
270 : /// children: <Widget>[
271 : /// Image.asset(
272 : /// data[index].image,
273 : /// fit: BoxFit.cover,
274 : /// ),
275 : /// Padding(
276 : /// padding: EdgeInsets.all(20.0),
277 : /// ),
278 : /// Column(
279 : /// children: <Widget>[
280 : /// Text(
281 : /// data[index].text1,
282 : /// style: WithPages.style,
283 : /// ),
284 : /// Text(
285 : /// data[index].text2,
286 : /// style: WithPages.style,
287 : /// ),
288 : /// Text(
289 : /// data[index].text3,
290 : /// style: WithPages.style,
291 : /// ),
292 : /// ],
293 : /// ),
294 : /// ],
295 : /// ),
296 : /// );
297 : /// },
298 : ///
299 : /// See Example for complete reference.
300 0 : LiquidSwipe.builder({
301 : Key? key,
302 : required IndexedWidgetBuilder itemBuilder,
303 : required int itemCount,
304 : this.fullTransitionValue = FULL_TRANSITION_PX,
305 : this.initialPage = 0,
306 : this.slideIconWidget,
307 : this.positionSlideIcon = 0.8,
308 : this.enableLoop = true,
309 : this.liquidController,
310 : this.waveType = WaveType.liquidReveal,
311 : this.onPageChangeCallback,
312 : this.currentUpdateTypeCallback,
313 : this.slidePercentCallback,
314 : this.ignoreUserGestureWhileAnimating = false,
315 : this.disableUserGesture = false,
316 : this.enableSideReveal = false,
317 0 : }) : assert(itemCount > 0),
318 0 : assert(initialPage >= 0 && initialPage < itemCount),
319 0 : assert(positionSlideIcon >= 0 && positionSlideIcon <= 1),
320 : liquidSwipeChildDelegate =
321 0 : LiquidSwipeBuilderChildDelegate(itemBuilder, itemCount),
322 0 : super(key: key);
323 :
324 1 : @override
325 1 : State<StatefulWidget> createState() => _LiquidSwipe();
326 : }
327 :
328 : class _LiquidSwipe extends State<LiquidSwipe> with TickerProviderStateMixin {
329 : late LiquidController liquidController;
330 :
331 1 : @override
332 : void initState() {
333 3 : liquidController = widget.liquidController ?? LiquidController();
334 1 : super.initState();
335 : }
336 :
337 1 : @override
338 : Widget build(BuildContext context) {
339 1 : return ChangeNotifierProvider<LiquidProvider>(
340 1 : create: (BuildContext context) {
341 1 : return LiquidProvider(
342 2 : initialPage: widget.initialPage,
343 2 : loop: widget.enableLoop,
344 3 : length: widget.liquidSwipeChildDelegate.itemCount(),
345 : vsync: this,
346 2 : slideIcon: widget.positionSlideIcon,
347 2 : currentUpdateTypeCallback: widget.currentUpdateTypeCallback,
348 2 : slidePercentCallback: widget.slidePercentCallback,
349 2 : onPageChangeCallback: widget.onPageChangeCallback,
350 2 : disableGesture: widget.disableUserGesture,
351 2 : enableSideReveal: widget.enableSideReveal,
352 : );
353 : },
354 : child:
355 2 : Consumer(builder: (BuildContext context, LiquidProvider notifier, _) {
356 2 : liquidController.setContext(context);
357 1 : return Stack(
358 : alignment: Alignment.center,
359 1 : children: <Widget>[
360 2 : notifier.slideDirection == SlideDirection.leftToRight
361 0 : ? widget.liquidSwipeChildDelegate
362 0 : .getChildAtIndex(context, notifier.activePageIndex)
363 2 : : widget.liquidSwipeChildDelegate
364 2 : .getChildAtIndex(context, notifier.nextPageIndex),
365 : //Pages
366 1 : PageReveal(
367 : //next page reveal
368 1 : horizontalReveal: notifier.slidePercentHor,
369 2 : child: notifier.slideDirection == SlideDirection.leftToRight
370 0 : ? widget.liquidSwipeChildDelegate
371 0 : .getChildAtIndex(context, notifier.nextPageIndex)
372 2 : : widget.liquidSwipeChildDelegate
373 2 : .getChildAtIndex(context, notifier.activePageIndex),
374 1 : slideDirection: notifier.slideDirection,
375 1 : iconSize: notifier.iconSize,
376 2 : waveType: widget.waveType,
377 1 : verticalReveal: notifier.slidePercentVer,
378 1 : enableSideReveal: notifier.enableSideReveal,
379 : ),
380 1 : PageDragger(
381 : //Used for gesture control
382 2 : fullTransitionPX: widget.fullTransitionValue,
383 2 : slideIconWidget: widget.slideIconWidget,
384 2 : iconPosition: widget.positionSlideIcon,
385 : ignoreUserGestureWhileAnimating:
386 2 : widget.ignoreUserGestureWhileAnimating,
387 : ), //PageDragger
388 : ], //Widget//Stack
389 : );
390 : }),
391 : ); //Scaffold
392 : }
393 : }
|