Build a Sneaker Store Mobile App With Navigation animation | Devhubspot
Learn how to build a Flutter online shop app. This could be used as an e-commerce app. This is a Flutter Shopping app for Android and iOS. We will build a beautiful online store app for iOS and Android. It covers beautiful animation and scrolling. This tutorial covers awesome animation UI design. By the end of this tutorial, you will master
Create a Flutter App
If everything is properly set up, then to create a project we can simply run the following command in our desired local directory:
flutter create sneakerapp
After we've set up the project, we can navigate inside the project directory and execute the following command in the terminal to run the project in either an available emulator or an actual device:
flutter run
First, we need to make some simple configurations to the default boilerplate code in the main.dart file. We'll remove some default code and add the following code
import 'package:flutter/material.dart';
import 'package:shoesapp/screens/home.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Shoes App',
debugShowCheckedModeBanner: false,
// theme: ThemeData(
// colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
// useMaterial3: true,
// ),
home: const HomeScreen());
}
}
Before Starting the code create a widgets folder and create shoepage.dart file inner widgets folder and add the following code :
import 'package:flutter/material.dart';
import 'package:shoesapp/screens/detail.dart';
class ShoesPage extends StatefulWidget {
const ShoesPage({super.key});
@override
State<ShoesPage> createState() => _ShoesPageState();
}
class _ShoesPageState extends State<ShoesPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFFCFAF8),
body: ListView(
children: [
SizedBox(height: 15.0),
Container(
padding: EdgeInsets.only(right: 15.0),
width: MediaQuery.of(context).size.width - 30.0,
height: MediaQuery.of(context).size.height - 50.0,
child: GridView.count(
crossAxisCount: 2,
primary: false,
crossAxisSpacing: 10.0,
mainAxisSpacing: 15.0,
childAspectRatio: 0.8,
children: [
buildShoeCard('S Shoes', '\$3.99', 'assets/images/1.jpg', false,
false, context),
buildShoeCard('Havy Shoes', '\$6.99', 'assets/images/6.jpg',
true, true, context),
buildShoeCard('Sport Shoes', '\$2.99', 'assets/images/3.jpg',
false, false, context),
buildShoeCard('L Shoes', '\$4.99', 'assets/images/4.jpg', true,
false, context),
buildShoeCard('L Shoes', '\$5.99', 'assets/images/2.jpg', false,
true, context),
buildShoeCard('P Shoes', '\$7.99', 'assets/images/7.jpg', true,
false, context),
],
),
),
SizedBox(height: 15.0),
],
),
);
}
Widget buildShoeCard(String name, String price, String imgPath, bool added,
bool isFavorite, context) {
return Padding(
padding: EdgeInsets.all(5.0),
child: InkWell(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
DetailScreen(assetPath: imgPath, price: price, name: name)));
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 3.0,
blurRadius: 5.0)
],
color: Colors.white),
child: Column(
children: [
Padding(
padding: EdgeInsets.all(5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
isFavorite
? Icon(Icons.favorite, color: Color(0xFFEF7532))
: Icon(
Icons.favorite_border,
color: Color(0xFFEF7532),
)
],
),
),
Hero(
tag: imgPath,
child: Container(
height: 80,
width: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(imgPath), fit: BoxFit.contain)),
)),
SizedBox(
height: 7.0,
),
Text(
price,
style: TextStyle(color: Color(0xFFCC8053), fontSize: 14.0),
),
Text(
name,
style: TextStyle(color: Color(0xFFCC8053), fontSize: 14.0),
),
Padding(
padding: EdgeInsets.all(8.0),
child: Container(
color: Color(0xFFEBEBEB),
height: 1.0,
),
),
Padding(
padding: EdgeInsets.only(left: 5.0, right: 5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
if (!added) ...[
Icon(
Icons.shopping_basket,
color: Color(0xFFD17E50),
size: 18.0,
),
Text("Add to cart",
style: TextStyle(
fontSize: 18.0, color: Color(0xFFD17E50)))
],
if (added) ...[
Icon(
Icons.remove_circle_outline,
color: Color(0xFFD17E50),
size: 18.0,
),
Text("1",
style: TextStyle(
fontSize: 18.0,
color: Color(0xFFD17E50),
fontWeight: FontWeight.bold)),
Icon(
Icons.add_circle_outline,
color: Color(0xFFD17E50),
size: 18.0,
)
]
],
),
)
],
),
),
),
);
}
}
After creating bottombar.dart file inner widgets folder add the following code :
import 'package:flutter/material.dart';
class BottomBar extends StatelessWidget {
const BottomBar({super.key});
@override
Widget build(BuildContext context) {
return BottomAppBar(
shape: CircularNotchedRectangle(),
notchMargin: 6.0,
color: Colors.transparent,
elevation: 9.0,
clipBehavior: Clip.antiAlias,
child: Container(
height: 50.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(25.0),
topRight: Radius.circular(25.0)),
color: Colors.white),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: 50.0,
width: MediaQuery.of(context).size.width / 2 - 40.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Icon(Icons.home, color: Color(0xFFEF7532)),
Icon(Icons.person_outline, color: Color(0xFFEF7532))
],
),
),
Container(
height: 50.0,
width: MediaQuery.of(context).size.width / 2 - 40.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Icon(Icons.search, color: Color(0xFFEF7532)),
Icon(Icons.shopping_basket, color: Color(0xFFEF7532))
],
),
)
],
),
),
);
}
}
After Create home.dart
stateful widget file in the screens folder like screens/home.dart, then inside of it with the following code:
import 'package:flutter/material.dart';
import 'package:shoesapp/widgets/bottombar.dart';
import 'package:shoesapp/widgets/shoepage.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen>
with SingleTickerProviderStateMixin {
late TabController _tabController;
@override
void initState() {
// TODO: implement initState
super.initState();
_tabController = TabController(length: 3, vsync: this);
}
@override
void dispose() {
// TODO: implement dispose
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0.0,
centerTitle: true,
leading: IconButton(
icon: Icon(
Icons.menu_rounded,
color: Color(0xFF545D68),
),
onPressed: () {},
),
title: Text(
"Home",
style: TextStyle(fontSize: 20.0, color: Color(0xFF545D68)),
),
actions: [
IconButton(
onPressed: () {},
icon: Icon(
Icons.notifications_none,
color: Color(0xFF545D68),
))
],
),
body: ListView(
padding: EdgeInsets.only(left: 20.0),
children: [
SizedBox(
height: 15.0,
),
TabBar(
controller: _tabController,
indicatorColor: Colors.transparent,
labelColor: Color(0xFFc88D67),
isScrollable: true,
labelPadding: EdgeInsets.only(right: 45.0),
unselectedLabelColor: Color(0xFFCDCDCD),
tabs: [
Tab(
child: Text("All", style: TextStyle(fontSize: 21.0)),
),
Tab(
child: Text("Latest", style: TextStyle(fontSize: 21.0)),
),
Tab(
child: Text("Upcoming", style: TextStyle(fontSize: 21.0)),
)
],
),
Container(
height: MediaQuery.of(context).size.height - 50.0,
width: double.infinity,
child: TabBarView(
controller: _tabController,
children: [ShoesPage(), ShoesPage(), ShoesPage()],
),
)
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
backgroundColor: Color(0xFFF17532),
child: Icon(Icons.dashboard),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomBar(),
);
}
}
After Create detail.dart
stateful widget file in the screens folder like screens/detail.dart, then inside of it with the following code:
import 'package:flutter/material.dart'; import 'package:shoesapp/widgets/bottombar.dart'; class DetailScreen extends StatelessWidget { final assetPath, price, name; const DetailScreen( {super.key, required this.assetPath, required this.price, required this.name}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.white, elevation: 0.0, centerTitle: true, leading: IconButton( icon: Icon( Icons.arrow_back, color: Color(0xFF545D68), ), onPressed: () { Navigator.of(context).pop(); }, ), title: Text(name, style: TextStyle(fontSize: 20.0, color: Color(0xFF545D68))), actions: [ IconButton( onPressed: () {}, icon: Icon( Icons.notifications_none, color: Color(0xFF545D68), )) ], ), body: ListView( children: [ SizedBox( height: 15.0, ), Padding( padding: EdgeInsets.only(left: 20.0, right: 20.0), child: Hero( tag: assetPath, child: Image.asset( assetPath, height: 250, width: double.infinity, fit: BoxFit.cover, ), ), ), SizedBox( height: 20.0, ), Center( child: Text(price, style: TextStyle( fontSize: 22.0, fontWeight: FontWeight.bold, color: Color(0xFF575E67))), ), SizedBox( height: 10.0, ), Center( child: Text(name, style: TextStyle( fontSize: 24.0, fontWeight: FontWeight.bold, color: Color(0xFF575E67))), ), SizedBox( height: 20.0, ), Center( child: Container( width: MediaQuery.of(context).size.width - 50.0, child: Text( 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since ', textAlign: TextAlign.center, style: TextStyle(fontSize: 16.0, color: Color(0xFFB4B8B9)), ), ), ), SizedBox( height: 20.0, ), Center( child: Container( width: MediaQuery.of(context).size.width - 50.0, height: 50.0, decoration: BoxDecoration( borderRadius: BorderRadius.circular(25.0), color: Color(0xFFF17532)), child: Center( child: Text( "Add to cart", style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.bold, color: Colors.white), ), ), ), ) ], ), floatingActionButton: FloatingActionButton( onPressed: () {}, backgroundColor: Color(0xFFF17532), child: Icon(Icons.dashboard), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, bottomNavigationBar: BottomBar(), ); } }