Skip to content

Commit b469ee6

Browse files
committed
🔥 solved challange 4 - feat: Drinks Selection Screen #5
1 parent b5b6f84 commit b469ee6

File tree

4 files changed

+354
-111
lines changed

4 files changed

+354
-111
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:drinks_selection_screen/widgets/image_carousel.dart';
3+
import 'package:drinks_selection_screen/widgets/logo_widget.dart';
4+
import 'data.dart';
5+
6+
class HomeScreen extends StatefulWidget {
7+
const HomeScreen({super.key});
8+
9+
@override
10+
State<HomeScreen> createState() => _HomeScreenState();
11+
}
12+
13+
class _HomeScreenState extends State<HomeScreen> {
14+
final PageController _pageController = PageController();
15+
Color _backgroundColor = const Color(0xffb71c1c);
16+
17+
void _onPageChanged(int index) {
18+
setState(() {
19+
_backgroundColor = coffeeList[index].backgroundColor;
20+
_pageController.animateToPage(
21+
index,
22+
duration: const Duration(milliseconds: 500),
23+
curve: Curves.easeOutQuad,
24+
);
25+
});
26+
}
27+
28+
@override
29+
Widget build(BuildContext context) {
30+
return Scaffold(
31+
backgroundColor: const Color(0xfff5f5f5),
32+
body: Stack(
33+
children: [
34+
AnimatedContainer(
35+
duration: const Duration(milliseconds: 500),
36+
decoration: BoxDecoration(
37+
gradient: LinearGradient(
38+
begin: Alignment.topLeft,
39+
end: Alignment.bottomRight,
40+
colors: [_backgroundColor, Colors.redAccent],
41+
),
42+
),
43+
child: Stack(
44+
children: [
45+
Center(
46+
child: Container(
47+
height: 250,
48+
width: 250,
49+
decoration: BoxDecoration(
50+
shape: BoxShape.circle,
51+
boxShadow: [
52+
BoxShadow(
53+
color: Colors.redAccent.withOpacity(0.3),
54+
blurRadius: 120,
55+
spreadRadius: 20,
56+
),
57+
],
58+
),
59+
),
60+
),
61+
Scaffold(
62+
backgroundColor: Colors.transparent,
63+
body: Padding(
64+
padding: const EdgeInsets.all(15),
65+
child: Column(
66+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
67+
children: [
68+
const LogoWidget(),
69+
_buildCoffeeList(),
70+
],
71+
),
72+
),
73+
),
74+
],
75+
),
76+
),
77+
CustomImageCarousel(
78+
onPageChange: _onPageChanged,
79+
),
80+
],
81+
),
82+
);
83+
}
84+
85+
Widget _buildCoffeeList() {
86+
return Container(
87+
height: 380,
88+
width: double.infinity,
89+
margin: const EdgeInsets.all(10),
90+
decoration: BoxDecoration(
91+
borderRadius: BorderRadius.circular(25),
92+
color: Colors.white,
93+
boxShadow: const [
94+
BoxShadow(
95+
color: Color(0x33000000),
96+
blurRadius: 20,
97+
spreadRadius: 2,
98+
),
99+
],
100+
),
101+
padding: const EdgeInsets.all(20),
102+
child: Column(
103+
crossAxisAlignment: CrossAxisAlignment.start,
104+
children: [
105+
const SizedBox(height: 25),
106+
Expanded(
107+
child: PageView.builder(
108+
controller: _pageController,
109+
scrollDirection: Axis.vertical,
110+
physics: const NeverScrollableScrollPhysics(),
111+
itemCount: coffeeList.length,
112+
itemBuilder: (context, index) {
113+
final coffee = coffeeList[index];
114+
return Column(
115+
crossAxisAlignment: CrossAxisAlignment.start,
116+
children: [
117+
RichText(
118+
text: TextSpan(
119+
children: [
120+
TextSpan(
121+
text: 'Giá: ',
122+
style: TextStyle(
123+
color: Colors.white,
124+
fontSize: 20,
125+
fontWeight: FontWeight.w400,
126+
shadows: [
127+
Shadow(
128+
blurRadius: 5.0,
129+
color: Colors.black.withOpacity(0.9),
130+
offset: const Offset(1.0, 1.0),
131+
),
132+
],
133+
),
134+
),
135+
TextSpan(
136+
text: ' ${coffee.price} ',
137+
style: const TextStyle(
138+
color: Colors.black,
139+
fontWeight: FontWeight.bold,
140+
fontSize: 28,
141+
),
142+
),
143+
const TextSpan(
144+
text: 'đ',
145+
style: TextStyle(
146+
color: Colors.black,
147+
fontWeight: FontWeight.bold,
148+
fontSize: 25,
149+
),
150+
),
151+
],
152+
),
153+
),
154+
const SizedBox(height: 20),
155+
Text(
156+
coffee.title,
157+
style: const TextStyle(
158+
fontSize: 24,
159+
fontWeight: FontWeight.bold,
160+
color: Color(0xffd32f2f),
161+
),
162+
),
163+
const SizedBox(height: 20),
164+
Text(
165+
coffee.description,
166+
style: const TextStyle(
167+
fontSize: 16,
168+
color: Colors.black87,
169+
),
170+
maxLines: 4,
171+
overflow: TextOverflow.ellipsis,
172+
),
173+
],
174+
);
175+
},
176+
),
177+
),
178+
_buildOrderButton(),
179+
],
180+
),
181+
);
182+
}
183+
184+
Widget _buildOrderButton() {
185+
return Container(
186+
height: 55,
187+
width: double.infinity,
188+
decoration: BoxDecoration(
189+
borderRadius: BorderRadius.circular(30),
190+
gradient: const LinearGradient(
191+
colors: [
192+
Color(0xffb71c1c),
193+
Color(0xff000000),
194+
Color(0xfff44336),
195+
],
196+
begin: Alignment.topLeft,
197+
end: Alignment.bottomRight,
198+
),
199+
boxShadow: const [
200+
BoxShadow(
201+
color: Color(0x30000000),
202+
blurRadius: 30,
203+
spreadRadius: 5,
204+
offset: Offset(10, 10),
205+
),
206+
],
207+
),
208+
alignment: Alignment.center,
209+
child: const Text(
210+
"ĐẶT NGAY",
211+
style: TextStyle(
212+
color: Colors.white,
213+
fontWeight: FontWeight.w800,
214+
fontSize: 18,
215+
),
216+
),
217+
);
218+
}
219+
}

drinks_selection_screen/lib/main.dart

+4-111
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,18 @@
11
import 'package:flutter/material.dart';
22

3+
import 'home_screen.dart';
4+
35
void main() {
46
runApp(const MyApp());
57
}
68

79
class MyApp extends StatelessWidget {
810
const MyApp({super.key});
911

10-
// This widget is the root of your application.
11-
@override
12-
Widget build(BuildContext context) {
13-
return MaterialApp(
14-
title: 'Flutter Demo',
15-
theme: ThemeData(
16-
// This is the theme of your application.
17-
//
18-
// TRY THIS: Try running your application with "flutter run". You'll see
19-
// the application has a purple toolbar. Then, without quitting the app,
20-
// try changing the seedColor in the colorScheme below to Colors.green
21-
// and then invoke "hot reload" (save your changes or press the "hot
22-
// reload" button in a Flutter-supported IDE, or press "r" if you used
23-
// the command line to start the app).
24-
//
25-
// Notice that the counter didn't reset back to zero; the application
26-
// state is not lost during the reload. To reset the state, use hot
27-
// restart instead.
28-
//
29-
// This works for code too, not just values: Most code changes can be
30-
// tested with just a hot reload.
31-
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
32-
useMaterial3: true,
33-
),
34-
home: const MyHomePage(title: 'Flutter Demo Home Page'),
35-
);
36-
}
37-
}
38-
39-
class MyHomePage extends StatefulWidget {
40-
const MyHomePage({super.key, required this.title});
41-
42-
// This widget is the home page of your application. It is stateful, meaning
43-
// that it has a State object (defined below) that contains fields that affect
44-
// how it looks.
45-
46-
// This class is the configuration for the state. It holds the values (in this
47-
// case the title) provided by the parent (in this case the App widget) and
48-
// used by the build method of the State. Fields in a Widget subclass are
49-
// always marked "final".
50-
51-
final String title;
52-
53-
@override
54-
State<MyHomePage> createState() => _MyHomePageState();
55-
}
56-
57-
class _MyHomePageState extends State<MyHomePage> {
58-
int _counter = 0;
59-
60-
void _incrementCounter() {
61-
setState(() {
62-
// This call to setState tells the Flutter framework that something has
63-
// changed in this State, which causes it to rerun the build method below
64-
// so that the display can reflect the updated values. If we changed
65-
// _counter without calling setState(), then the build method would not be
66-
// called again, and so nothing would appear to happen.
67-
_counter++;
68-
});
69-
}
70-
7112
@override
7213
Widget build(BuildContext context) {
73-
// This method is rerun every time setState is called, for instance as done
74-
// by the _incrementCounter method above.
75-
//
76-
// The Flutter framework has been optimized to make rerunning build methods
77-
// fast, so that you can just rebuild anything that needs updating rather
78-
// than having to individually change instances of widgets.
79-
return Scaffold(
80-
appBar: AppBar(
81-
// TRY THIS: Try changing the color here to a specific color (to
82-
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
83-
// change color while the other colors stay the same.
84-
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
85-
// Here we take the value from the MyHomePage object that was created by
86-
// the App.build method, and use it to set our appbar title.
87-
title: Text(widget.title),
88-
),
89-
body: Center(
90-
// Center is a layout widget. It takes a single child and positions it
91-
// in the middle of the parent.
92-
child: Column(
93-
// Column is also a layout widget. It takes a list of children and
94-
// arranges them vertically. By default, it sizes itself to fit its
95-
// children horizontally, and tries to be as tall as its parent.
96-
//
97-
// Column has various properties to control how it sizes itself and
98-
// how it positions its children. Here we use mainAxisAlignment to
99-
// center the children vertically; the main axis here is the vertical
100-
// axis because Columns are vertical (the cross axis would be
101-
// horizontal).
102-
//
103-
// TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
104-
// action in the IDE, or press "p" in the console), to see the
105-
// wireframe for each widget.
106-
mainAxisAlignment: MainAxisAlignment.center,
107-
children: <Widget>[
108-
const Text(
109-
'You have pushed the button this many times:',
110-
),
111-
Text(
112-
'$_counter',
113-
style: Theme.of(context).textTheme.headlineMedium,
114-
),
115-
],
116-
),
117-
),
118-
floatingActionButton: FloatingActionButton(
119-
onPressed: _incrementCounter,
120-
tooltip: 'Increment',
121-
child: const Icon(Icons.add),
122-
), // This trailing comma makes auto-formatting nicer for build methods.
14+
return const MaterialApp(
15+
home: HomeScreen(),
12316
);
12417
}
12518
}

0 commit comments

Comments
 (0)