Skip to content

Commit 70d7452

Browse files
author
Kamil Klyta
committed
Initial ice cream indicator
1 parent e244ad0 commit 70d7452

File tree

11 files changed

+223
-1
lines changed

11 files changed

+223
-1
lines changed
49.8 KB
Loading
12.4 KB
Loading
3.57 KB
Loading
3.72 KB
Loading
3.76 KB
Loading
2.77 KB
Loading
5.61 KB
Loading
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
import 'package:custom_refresh_indicator/custom_refresh_indicator.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:flutter/widgets.dart';
4+
5+
class ParalaxConfig {
6+
final int level;
7+
final AssetImage image;
8+
9+
const ParalaxConfig({
10+
this.level,
11+
this.image,
12+
});
13+
}
14+
15+
class IceCreamIndicator extends StatefulWidget {
16+
final Widget child;
17+
18+
const IceCreamIndicator({
19+
Key key,
20+
@required this.child,
21+
}) : super(key: key);
22+
23+
@override
24+
_IceCreamIndicatorState createState() => _IceCreamIndicatorState();
25+
}
26+
27+
class _IceCreamIndicatorState extends State<IceCreamIndicator>
28+
with SingleTickerProviderStateMixin {
29+
static const _assets = <ParalaxConfig>[
30+
ParalaxConfig(
31+
image: AssetImage("assets/ice_cream_indicator/cup2.png"),
32+
level: 0,
33+
),
34+
ParalaxConfig(
35+
image: AssetImage("assets/ice_cream_indicator/spoon.png"),
36+
level: 1,
37+
),
38+
ParalaxConfig(
39+
image: AssetImage("assets/ice_cream_indicator/ice1.png"),
40+
level: 3,
41+
),
42+
ParalaxConfig(
43+
image: AssetImage("assets/ice_cream_indicator/ice3.png"),
44+
level: 4,
45+
),
46+
ParalaxConfig(
47+
image: AssetImage("assets/ice_cream_indicator/ice2.png"),
48+
level: 2,
49+
),
50+
ParalaxConfig(
51+
image: AssetImage("assets/ice_cream_indicator/cup.png"),
52+
level: 0,
53+
),
54+
ParalaxConfig(
55+
image: AssetImage("assets/ice_cream_indicator/mint.png"),
56+
level: 5,
57+
),
58+
];
59+
60+
static const _indicatorSize = 150.0;
61+
62+
IndicatorState _prevState;
63+
AnimationController _spoonController;
64+
@override
65+
void initState() {
66+
_spoonController =
67+
AnimationController(vsync: this, duration: const Duration(seconds: 1));
68+
super.initState();
69+
}
70+
71+
static final _spoonTween = CurveTween(curve: Curves.easeInOut);
72+
static const double _imageSize = 150.0;
73+
@override
74+
Widget build(BuildContext context) {
75+
return CustomRefreshIndicator(
76+
offsetToArmed: _indicatorSize,
77+
onRefresh: () => Future.delayed(const Duration(seconds: 4)),
78+
child: widget.child,
79+
builder: (
80+
BuildContext context,
81+
Widget child,
82+
IndicatorController controller,
83+
) {
84+
return Stack(
85+
children: <Widget>[
86+
AnimatedBuilder(
87+
animation: controller,
88+
builder: (BuildContext context, Widget _) {
89+
final currentState = controller.state;
90+
if (_prevState == IndicatorState.armed &&
91+
currentState == IndicatorState.loading) {
92+
_spoonController.repeat(reverse: true);
93+
} else if (_prevState == IndicatorState.loading &&
94+
_prevState != currentState) {
95+
_spoonController.stop();
96+
} else if (currentState == IndicatorState.idle &&
97+
_prevState != currentState) {
98+
_spoonController..value = 0.0;
99+
}
100+
_prevState = currentState;
101+
return SizedBox(
102+
height: controller.value * _indicatorSize,
103+
child: Stack(
104+
children: <Widget>[
105+
for (int i = 0; i < _assets.length; i++)
106+
if (i == 1)
107+
AnimatedBuilder(
108+
animation: _spoonController,
109+
child: Transform.translate(
110+
offset: Offset(
111+
0,
112+
(-_assets[i].level) *
113+
(20.0 *
114+
(controller.value.clamp(1.0, 1.5) -
115+
1.0)) +
116+
10,
117+
),
118+
child: OverflowBox(
119+
maxHeight: _imageSize,
120+
minHeight: _imageSize,
121+
child: Image(
122+
image: _assets[i].image,
123+
fit: BoxFit.contain,
124+
height: _imageSize,
125+
),
126+
),
127+
),
128+
builder: (context, child) {
129+
return Transform.rotate(
130+
angle: (-_spoonTween
131+
.transform(_spoonController.value)) *
132+
1.25,
133+
child: child,
134+
);
135+
},
136+
)
137+
else
138+
Transform.translate(
139+
offset: Offset(
140+
0,
141+
(-_assets[i].level) *
142+
(20.0 *
143+
(controller.value.clamp(1.0, 1.5) -
144+
1.0)) +
145+
10,
146+
),
147+
child: OverflowBox(
148+
maxHeight: _imageSize,
149+
minHeight: _imageSize,
150+
child: Image(
151+
image: _assets[i].image,
152+
fit: BoxFit.contain,
153+
height: _imageSize,
154+
),
155+
),
156+
)
157+
],
158+
),
159+
);
160+
},
161+
),
162+
AnimatedBuilder(
163+
builder: (context, _) {
164+
return Transform.translate(
165+
offset: Offset(0.0, controller.value * _indicatorSize),
166+
child: child,
167+
);
168+
},
169+
animation: controller,
170+
),
171+
],
172+
);
173+
},
174+
);
175+
}
176+
177+
@override
178+
void dispose() {
179+
_spoonController.dispose();
180+
super.dispose();
181+
}
182+
}

example/lib/main.dart

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:example/indicators/simple_indicator.dart';
22
import 'package:example/screens/example_indicator_screen.dart';
3+
import 'package:example/screens/ice_cream_indicator_screen.dart';
34
import 'package:example/screens/plane_indicator_screen.dart';
45
import 'package:flutter/material.dart';
56

@@ -16,11 +17,11 @@ class MyApp extends StatelessWidget {
1617
theme: ThemeData(
1718
primarySwatch: Colors.blue,
1819
),
19-
2020
home: MainScreen(),
2121
routes: {
2222
'/example': (context) => ExampleIndicatorScreen(),
2323
'/plane': (context) => PlaneIndicatorScreen(),
24+
'/ice_cream': (context) => IceCreamIndicatorScreen(),
2425
},
2526
);
2627
}
@@ -75,6 +76,18 @@ class MainScreen extends StatelessWidget {
7576
),
7677
),
7778
const SizedBox(height: 15),
79+
RaisedButton(
80+
child: Container(
81+
height: 50,
82+
alignment: Alignment.center,
83+
child: Text("Ice cream"),
84+
),
85+
onPressed: () => Navigator.pushNamed(
86+
context,
87+
'/ice_cream',
88+
),
89+
),
90+
const SizedBox(height: 15),
7891
RaisedButton(
7992
child: Container(
8093
height: 50,
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import 'package:example/indicators/ice_cream_indicator.dart';
2+
import 'package:example/widgets/example_app_bar.dart';
3+
import 'package:example/widgets/example_list.dart';
4+
import 'package:flutter/material.dart';
5+
import 'package:flutter/widgets.dart';
6+
7+
class IceCreamIndicatorScreen extends StatefulWidget {
8+
@override
9+
_IceCreamIndicatorScreenState createState() =>
10+
_IceCreamIndicatorScreenState();
11+
}
12+
13+
class _IceCreamIndicatorScreenState extends State<IceCreamIndicatorScreen> {
14+
@override
15+
Widget build(BuildContext context) {
16+
return Scaffold(
17+
backgroundColor: appBackgroundColor,
18+
appBar: const ExampleAppBar(),
19+
body: SafeArea(
20+
child: IceCreamIndicator(
21+
child: const ExampleList(),
22+
),
23+
),
24+
);
25+
}
26+
}

0 commit comments

Comments
 (0)