1
0
mirror of https://github.com/nisrulz/flutter-examples.git synced 2026-03-21 22:18:28 +00:00

New Example - Lunch App (#98)

This commit is contained in:
Sushan Shakya
2022-10-23 00:15:15 +05:45
committed by GitHub
parent 91d4d1b868
commit 4407e4362b
80 changed files with 1958 additions and 0 deletions

29
lunch_app/lib/main.dart Normal file
View File

@@ -0,0 +1,29 @@
import 'package:flutter/material.dart';
import 'package:lunch_app/views/prototype/food_detail_view.dart';
import 'views/prototype/home.dart';
void main() => runApp(LunchApp());
class LunchApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
iconTheme: IconThemeData(
color: Colors.white,
),
appBarTheme: AppBarTheme(
elevation: 0,
backgroundColor: Colors.transparent,
titleTextStyle: TextStyle(
color: Colors.black,
),
),
),
home: Home(),
// home: FoodDetailView(),
);
}
}

View File

@@ -0,0 +1,18 @@
import 'package:flutter/cupertino.dart';
class Category {
final String title;
final IconData icon;
Category(this.title, this.icon);
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is Category && other.title == title && other.icon == icon;
}
@override
int get hashCode => title.hashCode ^ icon.hashCode;
}

View File

@@ -0,0 +1,54 @@
import 'package:flutter/material.dart';
class BottomNav extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(10),
height: 60,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(15),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Column(
children: [
Expanded(
child: Icon(Icons.home),
),
],
),
),
Container(
height: 45,
width: 45,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: Icon(
Icons.link,
color: Colors.black,
),
),
Expanded(
child: Column(
children: [
Expanded(
child: Icon(
Icons.shopping_basket,
color: Colors.white.withOpacity(0.5),
),
),
],
),
),
],
),
);
}
}

View File

@@ -0,0 +1,96 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:lunch_app/views/prototype/widgets/carousel_indicator.dart';
class FoodDetailView extends StatefulWidget {
@override
_FoodDetailViewState createState() => _FoodDetailViewState();
}
class _FoodDetailViewState extends State<FoodDetailView> {
int _currentPage;
@override
void initState() {
super.initState();
_currentPage = 0;
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blueGrey,
appBar: AppBar(
title: Text("Deals of the week"),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
child: PageView.builder(
scrollDirection: Axis.horizontal,
itemCount: 3,
onPageChanged: (i) {
setState(() {
_currentPage = i;
});
},
itemBuilder: (c, i) {
return Image.asset(
"assets/images/burger.png",
fit: BoxFit.contain,
);
},
),
),
Padding(
padding: const EdgeInsets.only(left: 25, right: 25, bottom: 25),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CarouselIndicator(length: 3, selected: _currentPage),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Delicious Burger",
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 50,
color: Colors.white,
),
),
const SizedBox(height: 5),
Text(
"Who doesn't love a big,\ntender, juicy burger?",
style:
TextStyle(color: Colors.grey.shade300, height: 1.5),
),
const SizedBox(height: 15),
],
),
Container(
height: 50,
width: MediaQuery.of(context).size.width / 1.5,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(8)),
child: Center(
child: Text(
"Get Started",
style: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
),
),
],
),
),
],
),
);
}
}

View File

@@ -0,0 +1,48 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:lunch_app/views/prototype/widgets/category_selector.dart';
import 'package:lunch_app/views/prototype/widgets/food_lister.dart';
import 'package:lunch_app/views/prototype/widgets/options_selector.dart';
import 'bottom_nav/bottom_nav.dart';
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: SvgPicture.asset(
"assets/nav/drawer.svg",
width: 25,
color: Colors.black.withOpacity(0.7),
),
),
),
body: Column(
children: [
Expanded(
child: ListView(
children: [
OptionsSelector(
onChange: (x) {},
),
CategorySelector(
onChange: (cat) {},
),
FoodLister(),
],
),
),
BottomNav(),
],
),
);
}
}

View File

@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
class CarouselIndicator extends StatelessWidget {
final int length;
final int selected;
const CarouselIndicator(
{Key key, @required this.length, @required this.selected})
: super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
length,
(i) {
var active = i == selected;
return Container(
height: 8,
width: 8,
decoration: BoxDecoration(
color: active ? Colors.white : Colors.white.withOpacity(0.4),
shape: BoxShape.circle,
),
margin: const EdgeInsets.only(right: 5),
);
},
),
),
);
}
}

View File

@@ -0,0 +1,62 @@
import 'package:flutter/material.dart';
import 'package:lunch_app/model/prototype/category.dart';
import 'package:lunch_app/views/prototype/widgets/main_btn.dart';
class CategorySelector extends StatefulWidget {
final Function(Category) onChange;
const CategorySelector({Key key, @required this.onChange}) : super(key: key);
@override
_CategorySelectorState createState() => _CategorySelectorState();
}
class _CategorySelectorState extends State<CategorySelector> {
final List<Category> categories = [
Category("All", null),
Category("Foods", Icons.local_pizza),
Category("Drinks", Icons.local_drink_sharp),
];
int _current;
@override
void initState() {
super.initState();
_current = 0;
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 20.0),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: List.generate(
categories.length,
(i) {
var cur = categories[i];
return Padding(
padding: (i == 0)
? const EdgeInsets.symmetric(horizontal: 15.0)
: const EdgeInsets.only(right: 15),
child: MainBtn(
onTap: () {
setState(() {
_current = i;
});
widget.onChange(categories[i]);
},
title: cur.title,
icon: cur.icon,
active: i == _current,
),
);
},
),
),
),
);
}
}

View File

@@ -0,0 +1,152 @@
import 'package:flutter/material.dart';
import 'package:lunch_app/views/prototype/food_detail_view.dart';
class FoodLister extends StatefulWidget {
@override
_FoodListerState createState() => _FoodListerState();
}
class _FoodListerState extends State<FoodLister> {
final PageController controller =
PageController(initialPage: 2, viewportFraction: 0.9);
@override
Widget build(BuildContext context) {
return Container(
height: MediaQuery.of(context).size.width * 0.8,
child: PageView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
controller: controller,
itemBuilder: (c, i) {
return _ItemWidget();
},
),
);
}
}
class _ItemWidget extends StatefulWidget {
@override
__ItemWidgetState createState() => __ItemWidgetState();
}
class __ItemWidgetState extends State<_ItemWidget> {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context, MaterialPageRoute(builder: (c) => FoodDetailView()));
},
child: Container(
margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 5),
child: Stack(
children: [
_buildBackgroundCard(),
SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: _buildImage(),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 15, vertical: 10),
child: _buildDetails(),
),
),
],
),
),
],
),
),
);
}
Widget _buildBackgroundCard() {
return Column(
children: [
SizedBox(
height: MediaQuery.of(context).size.width * 0.8 * 0.2,
),
Expanded(
child: Container(
// margin: const EdgeInsets.only(top: 40.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white,
border: Border.all(
color: Colors.grey.shade300,
),
),
),
),
],
);
}
Widget _buildImage() {
return Center(
child: Image.asset(
"assets/images/burger.png",
fit: BoxFit.contain,
),
);
}
Widget _buildDetails() {
return Column(
children: [
Text(
"Hello Burger",
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 20,
),
overflow: TextOverflow.ellipsis,
),
Expanded(
child: Center(
child: Text(
"An 100% beef party whipped in a soft bean and topped with onion, cheese and tomato",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.grey.shade400,
fontWeight: FontWeight.w400,
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"\$3.58",
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 20,
color: Colors.green,
),
),
const SizedBox(width: 10),
Text(
"\$5.58",
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 20,
color: Colors.grey.shade400,
),
),
],
),
const SizedBox(height: 5),
],
);
}
}

View File

@@ -0,0 +1,61 @@
import 'package:flutter/material.dart';
class MainBtn extends StatelessWidget {
final IconData icon;
final String title;
final bool active;
final Function onTap;
const MainBtn({
Key key,
this.icon,
this.title = "All",
this.active = true,
this.onTap,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: MediaQuery.of(context).size.width / 3,
minHeight: 50,
),
child: Container(
decoration: BoxDecoration(
color: active ? Colors.blueGrey : null,
borderRadius: BorderRadius.circular(10),
border: active ? null : Border.all(color: Colors.grey.shade400),
),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
(icon != null)
? Row(
children: [
Icon(
icon,
color: active ? Colors.white : Colors.grey.shade400,
),
SizedBox(width: 4),
],
)
: SizedBox(),
Text(
title,
style: TextStyle(
fontWeight: FontWeight.w400,
color: active ? Colors.white : Colors.grey.shade400,
),
),
],
),
),
),
);
}
}

View File

@@ -0,0 +1,66 @@
import 'package:flutter/material.dart';
class OptionsSelector extends StatefulWidget {
final Function(String) onChange;
const OptionsSelector({Key key, @required this.onChange}) : super(key: key);
@override
_OptionsSelectorState createState() => _OptionsSelectorState();
}
class _OptionsSelectorState extends State<OptionsSelector> {
final List<String> options = ["Offers", "Foods", "Drinks"];
int _current;
@override
void initState() {
super.initState();
_current = 0;
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Padding(
padding: const EdgeInsets.fromLTRB(15, 10, 0, 10),
child: Row(
children: List.generate(
options.length,
(i) => Padding(
padding: const EdgeInsets.only(right: 20),
child: GestureDetector(
onTap: () {
setState(() {
_current = i;
});
widget.onChange(options[i]);
},
child: Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 5,
color:
(i == _current) ? Colors.amber : Colors.transparent,
),
),
),
child: Text(
options[i],
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.w500,
),
),
),
),
),
),
),
),
);
}
}