|
1 | 1 | # Flutter Custom Refresh Indicator
|
2 | 2 |
|
3 |
| -This package provides `CustomRefreshIndicator` widget that make it easy to implement your own custom refresh indicator. |
| 3 | +This package provides `CustomRefreshIndicator` widget that make it easy to implement your own custom refresh indicator. It listens for scroll events from scroll widget passed to child argument and parsing it to data easy for custom refresh indicator implementation. Indicator data is provided by IndicatorController (third argument of builder method). Long story short... thats it! |
| 4 | + |
| 5 | +If there is something that can be improved, fixed or you just have some great idea feel free to open github issue [HERE](https://github.com/gonuit/flutter-custom-refresh-indicator/issues) or open a pull request [HERE](https://github.com/gonuit/flutter-custom-refresh-indicator/pulls). |
| 6 | + |
| 7 | +If you implemented your own custom refresh indicator with this library and you want it to be mentioned here or provided as an example to the eample app, just open a pull request [HERE](https://github.com/gonuit/flutter-custom-refresh-indicator/pulls). |
| 8 | + |
| 9 | +## QUICK START |
| 10 | + |
| 11 | +### Code |
4 | 12 |
|
5 |
| -## Usage |
6 | 13 | ```dart
|
7 | 14 | CustomRefreshIndicator(
|
8 |
| - // Your custom indicator builder |
9 |
| - indicatorBuilder: (context, data) => SimpleIndicatorContainer( |
10 |
| - data: data, |
11 |
| - child: SimpleIndicatorContent(data: data), |
12 |
| - ), |
13 |
| - onRefresh: myAsyncRefreshMethod, |
14 |
| - // Your child scroll widget |
| 15 | + /// Scrollable widget |
15 | 16 | child: ListView.separated(
|
16 | 17 | itemBuilder: (BuildContext context, int index) => const SizedBox(
|
17 | 18 | height: 100,
|
18 | 19 | ),
|
19 | 20 | separatorBuilder: (BuildContext context, int index) =>
|
20 | 21 | const SizedBox(height: 20),
|
21 | 22 | ),
|
| 23 | + /// Custom indicator builder function |
| 24 | + builder: ( |
| 25 | + BuildContext context, |
| 26 | + Widget child, |
| 27 | + IndicatorController controller, |
| 28 | + ) { |
| 29 | + /// TODO: Implement your own refresh indicator |
| 30 | + return Stack( |
| 31 | + children: <Widget>[ |
| 32 | + AnimatedBuilder( |
| 33 | + animation: controller, |
| 34 | + builder: (BuildContext context, _) { |
| 35 | + /// This part will be rebuild on every controller change |
| 36 | + return MyIndicator(); |
| 37 | + }, |
| 38 | + ), |
| 39 | + /// Scrollable widget that was provided as [child] argument |
| 40 | + /// |
| 41 | + /// TIP: |
| 42 | + /// You can also wrap [child] with [Transform] widget to also a animate list transform (see example app) |
| 43 | + child, |
| 44 | + ], |
| 45 | + ); |
| 46 | + } |
| 47 | + /// A function that's called when the user has dragged the refresh indicator |
| 48 | + /// far enough to demonstrate that they want the app to refresh. |
| 49 | + /// Should return [Future]. |
| 50 | + onRefresh: myAsyncRefreshMethod, |
22 | 51 | )
|
23 | 52 | ```
|
24 | 53 |
|
25 |
| -## Getting started |
| 54 | +### How the controller data change |
| 55 | + |
| 56 | +The best way to understand how the "CustomRefreshIndicator" widget changes its controller data is to see the example 😉. |
| 57 | + |
26 | 58 |
|
27 | 59 | ## Examples
|
28 |
| -### Use of `SimpleIndicatorContainer` with `Icon` as child [LINK](example/lib/indicators/simple_indicator.dart) |
29 |
| - |
30 | 60 |
|
31 |
| -### Envelope indicator |
32 |
| - |
| 61 | +Almost all of these examples are available in the example application. |
33 | 62 |
|
| 63 | +### Plane indicator [[SOURCE CODE](example/lib/indicators/plane_indicator.dart)] |
34 | 64 |
|
| 65 | + |
35 | 66 |
|
36 |
| -### `CustomRefreshIndicator` |
37 |
| -`CustomRefreshIndicator` has an absolute minimum functionality that allows you to create and set your own custom indicators. |
| 67 | +### Ice cream indicator [[SOURCE CODE](example/lib/indicators/ice_cream_indicator.dart)] |
38 | 68 |
|
39 |
| -#### Arguments |
40 |
| -| Argument | Type | Default value | Required | |
41 |
| -| :---------------------------------- | :-------------------------------------------------------------- | :----------------------------- | :---------------- | |
42 |
| -| child | `Widget` | none | true | |
43 |
| -| onRefresh | `Future<void> Function()` | none | true | |
44 |
| -| indicatorBuilder | `Widget Function(BuildContext, CustomRefreshIndicatorData) ` | none | true | |
45 |
| -| dragingToIdleDuration | `Duration` | `Duration(milliseconds: 300)` | false | |
46 |
| -| armedToLoadingDuration | `Duration` | `Duration(milliseconds: 200)` | false | |
47 |
| -| loadingToIdleDuration | `Duration` | `Duration(milliseconds: 100)` | false | |
48 |
| -| leadingGlowVisible | `bool` | `false` | false | |
49 |
| -| trailingGlowVisible | `bool` | `true` | false | |
| 69 | + |
50 | 70 |
|
| 71 | +### Simple indicator made with `PositionedIndicatorContainer` [[SOURCE CODE](example/lib/indicators/simple_indicator.dart)] |
51 | 72 |
|
52 |
| -### `CustomRefreshIndicatorData` |
53 |
| -Contains data provided by `CustomRefreshIndicator` that could be usefull for your custom indicator implementation. |
| 73 | + |
54 | 74 |
|
55 |
| -### Arguments |
| 75 | +### Envelope indicator |
| 76 | + |
| 77 | + |
| 78 | + |
| 79 | +### Emoji indicator [[SOURCE CODE](example/lib/indicators/emoji_indicator.dart)] |
| 80 | + |
| 81 | +You can create any indicator you want! |
56 | 82 |
|
57 |
| -| argument | type | |
58 |
| -| :----------------- | :---------------------------- | |
59 |
| -| value | `double` | |
60 |
| -| direction | `AxisDirection` | |
61 |
| -| scrollingDirection | `ScrollDirection` | |
62 |
| -| indicatorState | `IndicatorState` | |
| 83 | + |
63 | 84 |
|
64 |
| -#### value |
| 85 | +## CustomRefreshIndicator widget |
65 | 86 |
|
66 |
| -### `IndicatorState` |
67 |
| -Enum which describes state of CustomRefreshIndicator. |
| 87 | +`CustomRefreshIndicator` widget provides an absolute minimum functionality that allows you to create and set your own custom indicators. |
| 88 | + |
| 89 | +## IndicatorState |
| 90 | + |
| 91 | +Enum which describes state of CustomRefreshIndicator. It is provided by IndicatorController. |
68 | 92 |
|
69 | 93 | #### `idle`
|
70 |
| - `CustomRefreshIndicator` is idle (There is no action) |
71 |
| - |
72 |
| - (`CustomRefreshIndicatorData.value == 0`) |
| 94 | + |
| 95 | +CustomRefreshIndicator is idle (There is no action) |
| 96 | + |
| 97 | +```dart |
| 98 | +controller.value == 0.0 |
| 99 | +``` |
73 | 100 |
|
74 | 101 | #### `draging`
|
75 |
| - Whether user is draging `CustomRefreshIndicator` ending the scroll **WILL NOT** result in `onRefresh` call |
76 |
| - |
77 |
| - (`CustomRefreshIndicatorData.value < 1`) |
| 102 | + |
| 103 | +Whether the user is dragging a scrollable widget. |
| 104 | +Ending the scroll **WILL NOT** result in `onRefresh` function call |
| 105 | + |
| 106 | +```dart |
| 107 | +controller.value < 1.0 |
| 108 | +``` |
78 | 109 |
|
79 | 110 | #### `armed`
|
80 |
| - `CustomRefreshIndicator` is armed ending the scroll **WILL** result in: |
81 |
| - - `CustomRefreshIndicator.onRefresh` call |
82 |
| - - change of status to `loading` |
83 |
| - - decreasing `CustomRefreshIndicatorData.value` to `1` in duration specified by `CustomRefreshIndicator.armedToLoadingDuration`) |
84 |
| - |
85 |
| - (`CustomRefreshIndicatorData.value >= 1`) |
| 111 | + |
| 112 | +CustomRefreshIndicator is armed ending the scroll **WILL** result in: |
| 113 | + |
| 114 | +- `onRefresh` function call |
| 115 | +- change of indicator status to `loading` |
| 116 | +- decreasing controller.value to `1.0` in duration specified by `armedToLoadingDuration` CustomRefreshIndicator widget argument |
| 117 | + |
| 118 | +```dart |
| 119 | +controller.value >= 1.0 |
| 120 | +``` |
86 | 121 |
|
87 | 122 | #### `hiding`
|
88 |
| - CustomRefreshIndicator is hiding indicator when `onRefresh` future is resolved or indicator was canceled (scroll ended when [IndicatorState] was equal to `dragging` so `value` was less than `1` or the user started scrolling through the list) |
89 |
| - |
90 |
| - (`CustomRefreshIndicatorData.value` decreases to `0` in duration specified by `CustomRefreshIndicator.dragingToIdleDuration`) |
| 123 | + |
| 124 | +CustomRefreshIndicator is hiding its indicator. After the future returned from `onRefresh` function is completed or scroll ended when the state was equal to `dragging` or the user started scrolling through the list. |
| 125 | +controller value decreases to `0.0` in duration specified by `dragingToIdleDuration` CustomRefreshIndicator widget argument. |
| 126 | + |
| 127 | +```dart |
| 128 | +controller.value <= 1.0 |
| 129 | +``` |
91 | 130 |
|
92 | 131 | #### `loading`
|
93 |
| - `CustomRefreshIndicator` is awaiting on `onRefresh` call result. When `onRefresh` will resolve `CustomRefreshIndicator` will change state from `loading` to `hiding` and decrease `CustomRefreshIndicatorData.value` from `1` to `0` in duration specified by `CustomRefreshIndicator.loadingToIdleDuration` |
94 |
| - |
95 |
| - (`CustomRefreshIndicatorData.value == 1`) |
| 132 | + |
| 133 | +CustomRefreshIndicator widget is awaiting on future returned from `onRefresh` function. After future completed state will be change into `hiding` and controller value will decrease from `1.0` to `0.0` in duration specified by `loadingToIdleDuration` CustomRefreshIndicator widget argument. |
| 134 | + |
| 135 | +```dart |
| 136 | +controller.value == 1.0 |
| 137 | +``` |
0 commit comments