Skip to content

Commit 30e5f6c

Browse files
committed
🥚 Create Screen Home
1 parent 1709ec7 commit 30e5f6c

File tree

4 files changed

+262
-111
lines changed

4 files changed

+262
-111
lines changed

foods_selection_screen/lib/main.dart

+3-110
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:flutter/material.dart';
2+
import 'package:foods_selection_screen/presentation/home/home_screen.dart';
23

34
void main() {
45
runApp(const MyApp());
@@ -7,119 +8,11 @@ void main() {
78
class MyApp extends StatelessWidget {
89
const MyApp({super.key});
910

10-
// This widget is the root of your application.
1111
@override
1212
Widget build(BuildContext context) {
1313
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-
71-
@override
72-
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+
theme: ThemeData(scaffoldBackgroundColor: const Color(0xffebecf1)),
15+
home: const HomeScreen(),
12316
);
12417
}
12518
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:foods_selection_screen/data/food_data.dart';
3+
import 'widgets/menu_item_card.dart';
4+
5+
class HomeScreen extends StatelessWidget {
6+
const HomeScreen({super.key});
7+
8+
@override
9+
Widget build(BuildContext context) {
10+
return Scaffold(
11+
appBar: AppBar(
12+
backgroundColor: Colors.transparent,
13+
elevation: 0,
14+
leading: const Icon(Icons.sort, color: Colors.black),
15+
actions: [
16+
_buildActionIcon(context, Icons.shopping_cart),
17+
_buildActionIcon(context, Icons.search,
18+
margin: const EdgeInsets.only(right: 20)),
19+
],
20+
),
21+
body: Padding(
22+
padding: const EdgeInsets.all(20),
23+
child: Column(
24+
crossAxisAlignment: CrossAxisAlignment.start,
25+
children: [
26+
const Text(
27+
"MENU",
28+
style: TextStyle(
29+
fontSize: 40,
30+
fontWeight: FontWeight.bold,
31+
),
32+
),
33+
const SizedBox(height: 8),
34+
Text(
35+
"Đã đến lúc tận hưởng những điều tốt đẹp hơn trong cuộc sống",
36+
style: TextStyle(
37+
fontWeight: FontWeight.w500,
38+
color: Colors.grey.shade700,
39+
fontSize: 16,
40+
),
41+
),
42+
const SizedBox(height: 20),
43+
Expanded(
44+
child: GridView.builder(
45+
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
46+
crossAxisCount: 2,
47+
crossAxisSpacing: 15,
48+
mainAxisSpacing: 15,
49+
childAspectRatio: 0.55,
50+
),
51+
itemCount: items.length,
52+
itemBuilder: (context, index) {
53+
return MenuItemCard(data: items[index], index: index);
54+
},
55+
),
56+
),
57+
],
58+
),
59+
),
60+
);
61+
}
62+
63+
Widget _buildActionIcon(BuildContext context, IconData icon,
64+
{EdgeInsets? margin}) {
65+
return Container(
66+
height: 40,
67+
width: 40,
68+
margin: margin ?? const EdgeInsets.only(right: 15),
69+
decoration: BoxDecoration(
70+
color: Theme.of(context).scaffoldBackgroundColor,
71+
shape: BoxShape.circle,
72+
boxShadow: [
73+
BoxShadow(
74+
color: Colors.black26.withOpacity(0.2),
75+
offset: const Offset(2, 4),
76+
blurRadius: 6,
77+
),
78+
const BoxShadow(
79+
color: Colors.white70,
80+
offset: Offset(-2, -4),
81+
blurRadius: 6,
82+
),
83+
],
84+
),
85+
child: Icon(icon, color: Colors.black),
86+
);
87+
}
88+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:foods_selection_screen/data/food_data.dart';
3+
import 'package:foods_selection_screen/presentation/detail/detail_screen.dart';
4+
5+
class MenuItemCard extends StatefulWidget {
6+
final Item data;
7+
final int index;
8+
9+
const MenuItemCard({super.key, required this.data, required this.index});
10+
11+
@override
12+
State<MenuItemCard> createState() => _MenuItemCardState();
13+
}
14+
15+
class _MenuItemCardState extends State<MenuItemCard>
16+
with SingleTickerProviderStateMixin {
17+
late AnimationController _controller;
18+
19+
@override
20+
void initState() {
21+
super.initState();
22+
_controller = AnimationController(
23+
duration: const Duration(seconds: 5),
24+
vsync: this,
25+
)..repeat();
26+
}
27+
28+
@override
29+
void dispose() {
30+
_controller.dispose();
31+
super.dispose();
32+
}
33+
34+
@override
35+
Widget build(BuildContext context) {
36+
return GestureDetector(
37+
onTap: () {
38+
Navigator.push(
39+
context,
40+
MaterialPageRoute(
41+
builder: (context) =>
42+
DetailScreen(data: widget.data, tag: "${widget.index}"),
43+
),
44+
);
45+
},
46+
child: Stack(
47+
children: [
48+
Positioned(
49+
top: 50,
50+
right: 0,
51+
left: 0,
52+
bottom: 0,
53+
child: ClipRRect(
54+
borderRadius: BorderRadius.circular(20),
55+
child: Container(
56+
padding: const EdgeInsets.all(15),
57+
decoration: BoxDecoration(
58+
color: Colors.white,
59+
borderRadius: BorderRadius.circular(20),
60+
boxShadow: [
61+
BoxShadow(
62+
color: Colors.black26.withOpacity(0.1),
63+
offset: const Offset(4, 4),
64+
blurRadius: 10,
65+
),
66+
BoxShadow(
67+
color: Colors.white.withOpacity(0.8),
68+
offset: const Offset(-4, -4),
69+
blurRadius: 10,
70+
),
71+
],
72+
),
73+
child: Column(
74+
crossAxisAlignment: CrossAxisAlignment.center,
75+
mainAxisAlignment: MainAxisAlignment.end,
76+
children: [
77+
Text(
78+
widget.data.title,
79+
style: const TextStyle(
80+
fontWeight: FontWeight.bold,
81+
fontSize: 18,
82+
),
83+
textAlign: TextAlign.center,
84+
maxLines: 2,
85+
overflow: TextOverflow.ellipsis,
86+
),
87+
const SizedBox(height: 5),
88+
Text(
89+
"${widget.data.price} đ",
90+
style: TextStyle(
91+
fontSize: 16,
92+
color: Colors.grey.shade800,
93+
),
94+
),
95+
const SizedBox(height: 5),
96+
Row(
97+
mainAxisAlignment: MainAxisAlignment.center,
98+
children: List.generate(
99+
5,
100+
(s) => const Icon(
101+
Icons.star,
102+
color: Colors.orange,
103+
size: 15,
104+
),
105+
),
106+
),
107+
const SizedBox(height: 10),
108+
_buildAddToCartButton(),
109+
],
110+
),
111+
),
112+
),
113+
),
114+
Positioned(
115+
top: -12.5,
116+
right: 0,
117+
left: 0,
118+
child: RotationTransition(
119+
turns: _controller,
120+
child: CircleAvatar(
121+
radius: 75,
122+
backgroundColor: Colors.transparent,
123+
child: Hero(
124+
tag: "${widget.index}",
125+
child: Image.asset(
126+
widget.data.image,
127+
fit: BoxFit.cover,
128+
),
129+
),
130+
),
131+
),
132+
),
133+
],
134+
),
135+
);
136+
}
137+
138+
Widget _buildAddToCartButton() {
139+
return Container(
140+
margin: const EdgeInsets.symmetric(vertical: 10),
141+
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5),
142+
decoration: BoxDecoration(
143+
color: Colors.white,
144+
border: Border.all(color: Colors.grey.shade400),
145+
borderRadius: BorderRadius.circular(30),
146+
boxShadow: [
147+
BoxShadow(
148+
color: Colors.black26.withOpacity(0.1),
149+
offset: const Offset(2, 2),
150+
blurRadius: 5,
151+
),
152+
const BoxShadow(
153+
color: Colors.white70,
154+
offset: Offset(-2, -2),
155+
blurRadius: 5,
156+
),
157+
],
158+
),
159+
child: Text(
160+
"Gọi món",
161+
style: TextStyle(
162+
color: Colors.grey.shade800,
163+
fontWeight: FontWeight.bold,
164+
fontSize: 14,
165+
),
166+
),
167+
);
168+
}
169+
}

foods_selection_screen/pubspec.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ flutter:
5959
uses-material-design: true
6060

6161
# To add assets to your application, add an assets section, like this:
62-
# assets:
62+
assets:
63+
- assets/
6364
# - images/a_dot_burr.jpeg
6465
# - images/a_dot_ham.jpeg
6566

0 commit comments

Comments
 (0)