Flutter / Examples / * Project 2: Traveling App UI Design
Project 2: Travel App UI
-
Screen 1: Main
Sourece
https://www.youtube.com/watch?v=HC-FOF-SoFc&t=411s
UI1. Main Screen
main.dart
import 'package:flutter/material.dart'; import 'package:a/screens/splash_screen.dart'; import 'dart:ui'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { double screenWidth = window.physicalSize.width; return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData( scaffoldBackgroundColor: Color(0xffffff) ), home: SplashScreen(), ); } } 2. Splash Screen
screens/splash_screen.dart
add splashs screen background image1. Container : for bg image
add splash bodyimport 'package:flutter/material.dart'; class SplashScreen extends StatelessWidget { SplashScreen({super.key}); @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.all(25), decoration: BoxDecoration( color: Colors.black, image: DecorationImage( image: AssetImage("images/bg.jpg"), fit: BoxFit.cover, opacity: 0.5 ) ), ); } } 1. Column() : for dividing the main cell vertically
1. add title
import 'package:flutter/material.dart'; class SplashScreen extends StatelessWidget { SplashScreen({super.key}); @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.all(25), decoration: BoxDecoration( color: Colors.black, image: DecorationImage( image: AssetImage("images/bg.jpg"), fit: BoxFit.cover, opacity: 0.5 ) ), //*********************** */ //added new code // //*************** */ child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start , children: [ Align( alignment: Alignment.center, child: Text( "ASPEN", ), ) ], ) ); } } 2. add bottom text
1. RichText() : for applying different style to each text
import 'package:flutter/material.dart'; class SplashScreen extends StatelessWidget { SplashScreen({super.key}); @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.all(25), decoration: BoxDecoration( color: Colors.black, image: DecorationImage( image: AssetImage("images/bg.jpg"), fit: BoxFit.cover, opacity: 0.5 ) ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start , children: [ Align( alignment: Alignment.center, child: Text( "ASPEN", ), ), //********************** */ // added new code /// //*********************** */ Column( children: [ Container( margin: EdgeInsets.all(10), child: Align( alignment: Alignment.topLeft, child: RichText( text: TextSpan( children: [ TextSpan( text:"test1", style:TextStyle( fontSize: 24 ) ), TextSpan( text:"test2", style:TextStyle( fontSize: 40 ) ), TextSpan( text:"test3", style:TextStyle( fontSize: 40 ) ), ] ), ), ) ) ], ) ], ) ); } } 3. add button
import 'package:flutter/material.dart'; class SplashScreen extends StatelessWidget { SplashScreen({super.key}); @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.all(25), decoration: BoxDecoration( color: Colors.black, image: DecorationImage( image: AssetImage("images/bg.jpg"), fit: BoxFit.cover, opacity: 0.5 ) ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start , children: [ Align( alignment: Alignment.center, child: Text( "ASPEN", ), ), Column( children: [ Container( margin: EdgeInsets.all(10), child: Align( alignment: Alignment.topLeft, child: RichText( text: TextSpan( children: [ TextSpan( text:"test1", style:TextStyle( fontSize: 24 ) ), TextSpan( text:"test2", style:TextStyle( fontSize: 40 ) ), TextSpan( text:"test3", style:TextStyle( fontSize: 40 ) ), ] ), ), ) ), //**************************** */ // added new code //// //****************************** */ SizedBox(height: 10,), GestureDetector( onTap: (){}, child: Container( padding: EdgeInsets.symmetric(vertical: 15), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), color: Colors.red ), child: Center( child: Text( "Explore", style: TextStyle( color: Colors.white, fontSize: 20 ), ), ), ), ) ], ) ], ) ); } } 4. add navigation to button
onTap: (){ Navigator.push(context, MaterialPageRoute( builder: (context) => ExploreScreen() )); }, -
Screen 2: Explore Screen
1. Explore screen
file: screens/explore_screen.dart
1. main widgetimport 'package:flutter/material.dart'; class ExploreScreen extends StatelessWidget { ExploreScreen({super.key}); @override Widget build(BuildContext context) { return Container(); } } 2. change StatelessWidget to StatefulWidget1. define classes
import 'package:flutter/material.dart'; class ExploreScreen extends StatefulWidget { ExploreScreen({super.key}); @override //*********************** */ // 1. added new code /// //**************************** */ State createState() => _ExploreScreenState(); } //*********************** */ // 2. added new code /// //**************************** */ class _ExploreScreenState extends State { @override Widget build(BuildContext context) { return Container(); } } 2. Added initState() and dispose()
2. add bottom nav iconsimport 'package:flutter/material.dart'; class ExploreScreen extends StatefulWidget { ExploreScreen({super.key}); @override State createState() => _ExploreScreenState(); } class _ExploreScreenState extends State with SingleTickerProviderStateMixin{ //*************************** */ // added new code // //************************** */ late TabController _tabController; @override void initState(){ super.initState(); _tabController = TabController(length: 4, vsync: this); } @override void dispose(){ _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Container(); } } 1. SafeArea()
2. Scaffold() : for bottomNavBar
3. add header areaimport 'package:flutter/material.dart'; class ExploreScreen extends StatefulWidget { ExploreScreen({super.key}); @override State createState() => _ExploreScreenState(); } class _ExploreScreenState extends State with SingleTickerProviderStateMixin{ late TabController _tabController; @override void initState(){ super.initState(); _tabController = TabController(length: 4, vsync: this); } @override void dispose(){ _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { //******************* */ // aded new code /// //******************** */ return SafeArea( child: Scaffold( bottomNavigationBar: BottomNavigationBar( fixedColor: Color(0xFF176FF2), unselectedItemColor: Colors.black26, items: [ BottomNavigationBarItem( icon: Icon( Icons.home_filled, ), label: "Home" ), BottomNavigationBarItem( icon: Icon( Icons.search_off_outlined ), label: "Search" ), BottomNavigationBarItem( icon: Icon( Icons.favorite_outline ), label: "Favorite" ) ], ), ), ); } } 1. Column() : for dividing the main screen vertically
2. Padding : for packing and appling the padding to the header container
3. Row() : for dividing the header portion horizontally
4. Column(): for dividing the first cell in the header portion vertically
5. Row(): for dividing the second cell in the header portion horizontally
4. search barimport 'package:flutter/material.dart'; class ExploreScreen extends StatefulWidget { ExploreScreen({super.key}); @override State createState() => _ExploreScreenState(); } class _ExploreScreenState extends State with SingleTickerProviderStateMixin{ late TabController _tabController; @override void initState(){ super.initState(); _tabController = TabController(length: 4, vsync: this); } @override void dispose(){ _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, //********************* */ // **** summary 1 : for dividing the main screen vertically ***** // //******************** */ body: Column( children: [ //********************* */ // **** summary 2 : for packing and appling the padding to the header container ***** // //******************** */ Padding( padding: EdgeInsets.symmetric(vertical: 15), //********************* */ // **** summary 3 : for dividing the header portion horizontally ***** // //******************** */ child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ //********************* */ // **** summary 4 : for dividing the first cell in the header portion vertically ***** // //******************** */ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.symmetric(horizontal: 15), child: Text( "Explore", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400 ), ), ), Padding( padding: EdgeInsets.symmetric(horizontal: 15), child: Text( "ASPEN", style: TextStyle( fontSize: 32, fontWeight: FontWeight.w600 ), ), ), ], ), //********************* */ // **** summary 5 : for dividing the second cell in the header portion horizontally ***** // //******************** */ Row( children: [ Icon( Icons.location_city, color: Colors.lightBlue, ), SizedBox(width: 10,), Text( "Cochin", style: TextStyle( fontSize: 15, fontWeight: FontWeight.w300 ), ) ], ) ], ) ) ], ), bottomNavigationBar: BottomNavigationBar( fixedColor: Color(0xFF176FF2), unselectedItemColor: Colors.black26, items: [ BottomNavigationBarItem( icon: Icon( Icons.home_filled, ), label: "Home" ), BottomNavigationBarItem( icon: Icon( Icons.search_off_outlined ), label: "Search" ), BottomNavigationBarItem( icon: Icon( Icons.favorite_outline ), label: "Favorite" ) ], ), ), ); } } add the search panel after the header portion
1. Container()
5. tabBarimport 'package:flutter/material.dart'; class ExploreScreen extends StatefulWidget { ExploreScreen({super.key}); @override State createState() => _ExploreScreenState(); } class _ExploreScreenState extends State with SingleTickerProviderStateMixin{ late TabController _tabController; @override void initState(){ super.initState(); _tabController = TabController(length: 4, vsync: this); } @override void dispose(){ _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, body: Column( children: [ Padding( padding: EdgeInsets.symmetric(vertical: 15), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.symmetric(horizontal: 15), child: Text( "Explore", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400 ), ), ), Padding( padding: EdgeInsets.symmetric(horizontal: 15), child: Text( "ASPEN", style: TextStyle( fontSize: 32, fontWeight: FontWeight.w600 ), ), ), ], ), Row( children: [ Icon( Icons.location_city, color: Colors.lightBlue, ), SizedBox(width: 10,), Text( "Cochin", style: TextStyle( fontSize: 15, fontWeight: FontWeight.w300 ), ) ], ) ], ) ), //******************************* */ // added new code /// //******************************* */ Container( margin: EdgeInsets.only(left: 10.0, right: 10.0), padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15), decoration: BoxDecoration( color: Color(0xFFF3F8FE), borderRadius: BorderRadius.circular(24) ), child: TextField( decoration: InputDecoration( hintText: "Find place to visit", border:InputBorder.none, prefixIcon: Icon(Icons.search) ), ), ) ], ), bottomNavigationBar: BottomNavigationBar( fixedColor: Color(0xFF176FF2), unselectedItemColor: Colors.black26, items: [ BottomNavigationBarItem( icon: Icon( Icons.home_filled, ), label: "Home" ), BottomNavigationBarItem( icon: Icon( Icons.search_off_outlined ), label: "Search" ), BottomNavigationBarItem( icon: Icon( Icons.favorite_outline ), label: "Favorite" ) ], ), ), ); } } 1. TabBar()
6. Scrollable listingimport 'package:flutter/material.dart'; class ExploreScreen extends StatefulWidget { ExploreScreen({super.key}); @override State createState() => _ExploreScreenState(); } class _ExploreScreenState extends State with SingleTickerProviderStateMixin{ late TabController _tabController; @override void initState(){ super.initState(); _tabController = TabController(length: 4, vsync: this); } @override void dispose(){ _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, body: Column( children: [ Padding( padding: EdgeInsets.symmetric(vertical: 15), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.symmetric(horizontal: 15), child: Text( "Explore", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400 ), ), ), Padding( padding: EdgeInsets.symmetric(horizontal: 15), child: Text( "ASPEN", style: TextStyle( fontSize: 32, fontWeight: FontWeight.w600 ), ), ), ], ), Row( children: [ Icon( Icons.location_city, color: Colors.lightBlue, ), SizedBox(width: 10,), Text( "Cochin", style: TextStyle( fontSize: 15, fontWeight: FontWeight.w300 ), ) ], ) ], ) ), Container( margin: EdgeInsets.only(left: 10.0, right: 10.0), padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15), decoration: BoxDecoration( color: Color(0xFFF3F8FE), borderRadius: BorderRadius.circular(24) ), child: TextField( decoration: InputDecoration( hintText: "Find place to visit", border:InputBorder.none, prefixIcon: Icon(Icons.search) ), ), ), //********************************* */ // added new code // //*********************************** */ TabBar( controller: _tabController, indicatorColor: Color(0xFF176FF2), labelColor: Color(0xFF176FF2), unselectedLabelColor: Color(0xFFB8B8B8), tabs: [ Tab( text: "Location", ), Tab( text: "Hotel", ), Tab( text: "Food", ), Tab( text: "Advantures", ) ], ) ], ), bottomNavigationBar: BottomNavigationBar( fixedColor: Color(0xFF176FF2), unselectedItemColor: Colors.black26, items: [ BottomNavigationBarItem( icon: Icon( Icons.home_filled, ), label: "Home" ), BottomNavigationBarItem( icon: Icon( Icons.search_off_outlined ), label: "Search" ), BottomNavigationBarItem( icon: Icon( Icons.favorite_outline ), label: "Favorite" ) ], ), ), ); } } 1. Expanded
2. TabBarView
import 'package:flutter/material.dart'; class ExploreScreen extends StatefulWidget { ExploreScreen({super.key}); @override State createState() => _ExploreScreenState(); } class _ExploreScreenState extends State with SingleTickerProviderStateMixin{ late TabController _tabController; @override void initState(){ super.initState(); _tabController = TabController(length: 4, vsync: this); } @override void dispose(){ _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, body: Column( children: [ Padding( padding: EdgeInsets.symmetric(vertical: 15), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.symmetric(horizontal: 15), child: Text( "Explore", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400 ), ), ), Padding( padding: EdgeInsets.symmetric(horizontal: 15), child: Text( "ASPEN", style: TextStyle( fontSize: 32, fontWeight: FontWeight.w600 ), ), ), ], ), Row( children: [ Icon( Icons.location_city, color: Colors.lightBlue, ), SizedBox(width: 10,), Text( "Cochin", style: TextStyle( fontSize: 15, fontWeight: FontWeight.w300 ), ) ], ) ], ) ), Container( margin: EdgeInsets.only(left: 10.0, right: 10.0), padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15), decoration: BoxDecoration( color: Color(0xFFF3F8FE), borderRadius: BorderRadius.circular(24) ), child: TextField( decoration: InputDecoration( hintText: "Find place to visit", border:InputBorder.none, prefixIcon: Icon(Icons.search) ), ), ), TabBar( controller: _tabController, indicatorColor: Color(0xFF176FF2), labelColor: Color(0xFF176FF2), unselectedLabelColor: Color(0xFFB8B8B8), tabs: [ Tab( text: "Location", ), Tab( text: "Hotel", ), Tab( text: "Food", ), Tab( text: "Advantures", ) ], ), //****************************** */ // added new code // // *****************************// SizedBox(height: 20,), Expanded( child: TabBarView( controller: _tabController, children: [ buildTabContent("Location"), buildTabContent("Hotels"), buildTabContent("Food"), buildTabContent("Advanture"), ], ), ) ], ), bottomNavigationBar: BottomNavigationBar( fixedColor: Color(0xFF176FF2), unselectedItemColor: Colors.black26, items: [ BottomNavigationBarItem( icon: Icon( Icons.home_filled, ), label: "Home" ), BottomNavigationBarItem( icon: Icon( Icons.search_off_outlined ), label: "Search" ), BottomNavigationBarItem( icon: Icon( Icons.favorite_outline ), label: "Favorite" ) ], ), ), ); } } 7. buildTabContent widget
We can create the widget at the end of the class or in another file
1. Top portionimport 'package:flutter/material.dart'; class ExploreScreen extends StatefulWidget { ExploreScreen({super.key}); @override State createState() => _ExploreScreenState(); } class _ExploreScreenState extends State with SingleTickerProviderStateMixin{ late TabController _tabController; @override void initState(){ super.initState(); _tabController = TabController(length: 4, vsync: this); } @override void dispose(){ _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, body: Column( children: [ Padding( padding: EdgeInsets.symmetric(vertical: 15), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.symmetric(horizontal: 15), child: Text( "Explore", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400 ), ), ), Padding( padding: EdgeInsets.symmetric(horizontal: 15), child: Text( "ASPEN", style: TextStyle( fontSize: 32, fontWeight: FontWeight.w600 ), ), ), ], ), Row( children: [ Icon( Icons.location_city, color: Colors.lightBlue, ), SizedBox(width: 10,), Text( "Cochin", style: TextStyle( fontSize: 15, fontWeight: FontWeight.w300 ), ) ], ) ], ) ), Container( margin: EdgeInsets.only(left: 10.0, right: 10.0), padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15), decoration: BoxDecoration( color: Color(0xFFF3F8FE), borderRadius: BorderRadius.circular(24) ), child: TextField( decoration: InputDecoration( hintText: "Find place to visit", border:InputBorder.none, prefixIcon: Icon(Icons.search) ), ), ), TabBar( controller: _tabController, indicatorColor: Color(0xFF176FF2), labelColor: Color(0xFF176FF2), unselectedLabelColor: Color(0xFFB8B8B8), tabs: [ Tab( text: "Location", ), Tab( text: "Hotel", ), Tab( text: "Food", ), Tab( text: "Advantures", ) ], ), SizedBox(height: 20,), Expanded( child: TabBarView( controller: _tabController, children: [ buildTabContent("Location"), buildTabContent("Hotels"), buildTabContent("Food"), buildTabContent("Advanture"), ], ), ) ], ), bottomNavigationBar: BottomNavigationBar( fixedColor: Color(0xFF176FF2), unselectedItemColor: Colors.black26, items: [ BottomNavigationBarItem( icon: Icon( Icons.home_filled, ), label: "Home" ), BottomNavigationBarItem( icon: Icon( Icons.search_off_outlined ), label: "Search" ), BottomNavigationBarItem( icon: Icon( Icons.favorite_outline ), label: "Favorite" ) ], ), ), ); } //****************************** */ // added new code // // *****************************// Widget buildTabContent(String title){ return Container(); } } 1. SingleChildScrollView() - for listing
2. Column - for dividing vertically
3. Row - for dividing horizontally
2. listing portionWidget buildTabContent(String title){ return Padding( padding: EdgeInsets.symmetric(horizontal: 20), //************************************************** */ // summary 1. SingleChildScrollView() - for listing /// // ****************************************************// child: SingleChildScrollView( //************************************************** */ // summary 2. Column - for dividing vertically /// // ****************************************************// child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ //************************************************** */ // summary 3. Row - for dividing horizontally /// // ****************************************************// Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Popular", style: TextStyle( fontWeight: FontWeight.w600, fontSize: 18, color:Colors.red ), ), Text( "See All", style: TextStyle( fontWeight: FontWeight.w400, fontSize: 12, color:Colors.red ), ) ], ) ], ), ), ); } Widget buildTabContent(String title){ return Padding( padding: EdgeInsets.symmetric(horizontal: 20), child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Popular", style: TextStyle( fontWeight: FontWeight.w600, fontSize: 18, color:Colors.red ), ), Text( "See All", style: TextStyle( fontWeight: FontWeight.w400, fontSize: 12, color:Colors.red ), ) ], ), //********************************* */ // aded new code // //******************************* */ SizedBox(height: 20,), SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: [ PopularItem(title:"Item1", rating:"4.1", image:"images/bg.png"), SizedBox(width:10), PopularItem(title:"Item2", rating:"4.1", image:"images/bg.png"), SizedBox(width:10), PopularItem(title:"Item2", rating:"4.1", image:"images/bg.png"), ], ), ) ], ), ), ); } 3. Widget : PopularItem
file: widgets/popular_item.dart
1. define variables
2. define constructor
import 'package:flutter/material.dart'; class PopularItem extends StatelessWidget { final String title; final String rating; final String image; PopularItem({required this.title, required this.rating, required this.image}); @override Widget build(BuildContext context) { return Container(); } } 2. show image
1. Container() - for bg image
import 'package:flutter/material.dart'; class PopularItem extends StatelessWidget { final String title; final String rating; final String image; PopularItem({required this.title, required this.rating, required this.image}); @override Widget build(BuildContext context) { //*************************** */ // aded new code // // *************************// return GestureDetector( onTap: (){}, child: Container( width: 200, height: 240, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), image: DecorationImage( image: AssetImage(image), fit: BoxFit.cover ) ), ), ); } } 2. show body
1. Column - for dividing the cell vertically
2. Row for dividing the cell horicontally
3. Column for dividing the first cell vertically
3. add recommended listingimport 'package:flutter/material.dart'; class PopularItem extends StatelessWidget { final String title; final String rating; final String image; PopularItem({required this.title, required this.rating, required this.image}); @override Widget build(BuildContext context) { return GestureDetector( onTap: (){}, child: Container( width: 200, height: 240, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), image: DecorationImage( image: AssetImage(image), fit: BoxFit.cover ) ), //************************************ */ // added new code // //************************************** */ //************************************ */ // summary 1. Column - for dividing the cell vertically //************************************** */ child: Column( mainAxisAlignment: MainAxisAlignment.end, //crossAxisAlignment: CrossAxisAlignment.start, children: [ //************************************ */ // 2. Row for dividing the cell horicontally //************************************** */ Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ //************************************ */ // 3. Column for dividing the first cell vertically //************************************** */ Column( children: [ Container( padding: EdgeInsets.symmetric(vertical: 5, horizontal: 5), decoration: BoxDecoration( color: Colors.amber, borderRadius: BorderRadius.circular(10) ), child: Text( title ), ), Container( padding: EdgeInsets.symmetric(vertical: 5, horizontal: 5), decoration: BoxDecoration( color: Colors.amber, borderRadius: BorderRadius.circular(10) ), child: Row( children: [ Icon( Icons.star ), Text( rating ), ], ) ) ], ), Container( padding: EdgeInsets.all(5), decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.red ), child: Icon( Icons.favorite, color: Colors.white, ), ) ], ) ], ), ), ); } } file: screens/explore_screen.dart
import 'package:flutter/material.dart'; import 'package:a/widgets/popular_item.dart'; class ExploreScreen extends StatefulWidget { ExploreScreen({super.key}); @override State createState() => _ExploreScreenState(); } class _ExploreScreenState extends State with SingleTickerProviderStateMixin{ late TabController _tabController; @override void initState(){ super.initState(); _tabController = TabController(length: 4, vsync: this); } @override void dispose(){ _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, body: Column( children: [ Padding( padding: EdgeInsets.symmetric(vertical: 15), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.symmetric(horizontal: 15), child: Text( "Explore", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400 ), ), ), Padding( padding: EdgeInsets.symmetric(horizontal: 15), child: Text( "ASPEN", style: TextStyle( fontSize: 32, fontWeight: FontWeight.w600 ), ), ), ], ), Row( children: [ Icon( Icons.location_city, color: Colors.lightBlue, ), SizedBox(width: 10,), Text( "Cochin", style: TextStyle( fontSize: 15, fontWeight: FontWeight.w300 ), ) ], ) ], ) ), Container( margin: EdgeInsets.only(left: 10.0, right: 10.0), padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15), decoration: BoxDecoration( color: Color(0xFFF3F8FE), borderRadius: BorderRadius.circular(24) ), child: TextField( decoration: InputDecoration( hintText: "Find place to visit", border:InputBorder.none, prefixIcon: Icon(Icons.search) ), ), ), TabBar( controller: _tabController, indicatorColor: Color(0xFF176FF2), labelColor: Color(0xFF176FF2), unselectedLabelColor: Color(0xFFB8B8B8), tabs: [ Tab( text: "Location", ), Tab( text: "Hotel", ), Tab( text: "Food", ), Tab( text: "Advantures", ) ], ), SizedBox(height: 20,), Expanded( child: TabBarView( controller: _tabController, children: [ buildTabContent("Location"), buildTabContent("Hotels"), buildTabContent("Food"), buildTabContent("Advanture"), ], ), ) ], ), bottomNavigationBar: BottomNavigationBar( fixedColor: Color(0xFF176FF2), unselectedItemColor: Colors.black26, items: [ BottomNavigationBarItem( icon: Icon( Icons.home_filled, ), label: "Home" ), BottomNavigationBarItem( icon: Icon( Icons.search_off_outlined ), label: "Search" ), BottomNavigationBarItem( icon: Icon( Icons.favorite_outline ), label: "Favorite" ) ], ), ), ); } Widget buildTabContent(String title){ return Padding( padding: EdgeInsets.symmetric(horizontal: 20), child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Popular", style: TextStyle( fontWeight: FontWeight.w600, fontSize: 18, color:Colors.red ), ), Text( "See All", style: TextStyle( fontWeight: FontWeight.w400, fontSize: 12, color:Colors.red ), ) ], ), SizedBox(height: 20,), SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: [ PopularItem(title:"Item1", rating:"4.1", image:"images/bg.jpg"), SizedBox(width:10), PopularItem(title:"Item2", rating:"4.1", image:"images/bg.jpg"), SizedBox(width:10), PopularItem(title:"Item2", rating:"4.1", image:"images/bg.jpg"), ], ), ), //**************************** */ // added new code // //*************************** */ SizedBox(height: 20,), SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: [ RecommendedCard(title:"Item1", rating:"4.1", image:"images/bg.jpg"), SizedBox(width:10), RecommendedCard(title:"Item2", rating:"4.1", image:"images/bg.jpg"), SizedBox(width:10), RecommendedCard(title:"Item2", rating:"4.1", image:"images/bg.jpg"), ], ), ), ], ), ), ); } } widget : RecommendedCard
file: widgets/recommended_card.dart
copied from widgets/popular_item.dart
Page Navigationimport 'package:flutter/material.dart'; class RecommendedCard extends StatelessWidget { final String title; final String rating; final String image; RecommendedCard({required this.title, required this.rating, required this.image}); @override Widget build(BuildContext context) { return GestureDetector( onTap: (){}, child: Container( width: 200, height: 120, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), image: DecorationImage( image: AssetImage(image), fit: BoxFit.cover ) ), child: Column( mainAxisAlignment: MainAxisAlignment.end, //crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Column( children: [ Container( padding: EdgeInsets.symmetric(vertical: 5, horizontal: 5), decoration: BoxDecoration( color: Colors.amber, borderRadius: BorderRadius.circular(10) ), child: Text( title ), ), Container( padding: EdgeInsets.symmetric(vertical: 5, horizontal: 5), decoration: BoxDecoration( color: Colors.amber, borderRadius: BorderRadius.circular(10) ), child: Row( children: [ Icon( Icons.star ), Text( rating ), ], ) ) ], ), Container( padding: EdgeInsets.all(5), decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.red ), child: Icon( Icons.favorite, color: Colors.white, ), ) ], ) ], ), ), ); } } onTap: () { Navigator.push(context, MaterialPageRoute( builder: (context) => PlaceScreen() )); }, -
Screen 3: PlaceScreen
1. PlaceScreen
file: screens/place_screen.dart
1. bg imageimport 'package:flutter/material.dart'; class PlaceScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Container(); } } 1. SafeArea()
2. Scaffold() : for body
3. SingleChildScrollView () : for scrolling
4. Padding() : for packing the elements and apply padding
5. Column() : for dividing the screen vertically
6. Stack () : for placing the elements over the another elements
2. back buttonimport 'package:flutter/material.dart'; class PlaceScreen extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, body: SingleChildScrollView( child: Padding( padding: EdgeInsets.all((10)), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ Stack( clipBehavior: Clip.none, children: [ Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height/2, decoration: BoxDecoration( image: DecorationImage( image: AssetImage("images/bg.jpg"), fit: BoxFit.cover ) ), ) ], ) ], ), ), ), ), ); } } 1. Column() - for dividing the cell vertically
2. GestureDetector - for page naviagation
3. Container() - for appling decoration and shadow
3. add favorite iconimport 'package:flutter/material.dart'; class PlaceScreen extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, body: SingleChildScrollView( child: Padding( padding: EdgeInsets.all((10)), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ Stack( clipBehavior: Clip.none, children: [ Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height/2, decoration: BoxDecoration( image: DecorationImage( image: AssetImage("images/bg.jpg"), fit: BoxFit.cover ) ), //*********************************** */ //******added new code */ //********************************* */ child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( onTap: (){}, child: Container( margin: EdgeInsets.all(15), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 2, spreadRadius: 4 ) ] ), child: Icon( Icons.arrow_back_ios, color: Colors.red, ), ), ) ], ), ) ], ) ], ), ), ), ), ); } } 1. Positioned() for positioning item inside stack()
2. Container() for decoration and shadow
Stack() is used to place the favorite icon partially outside of the container()
3. Add Title and view mapimport 'package:flutter/material.dart'; class PlaceScreen extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, body: SingleChildScrollView( child: Padding( padding: EdgeInsets.all((10)), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ Stack( clipBehavior: Clip.none, children: [ Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height/2, decoration: BoxDecoration( image: DecorationImage( image: AssetImage("images/bg.jpg"), fit: BoxFit.cover ) ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( onTap: (){}, child: Container( margin: EdgeInsets.all(15), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 2, spreadRadius: 4 ) ] ), child: Icon( Icons.arrow_back_ios, color: Colors.red, size:20 ), ), ) ], ), ), //***************************** */ // added new code // //************************** */ Positioned( bottom: -30, right:20, child: Container( margin: EdgeInsets.all(15), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(25), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 2, spreadRadius: 4 ) ] ), child: Icon( Icons.favorite_outline, color: Colors.red, size:20 ), ), ) ], ) ], ), ), ), ), ); } } 1. Row() for dividing horizontally
5. add review and rating portionimport 'package:flutter/material.dart'; class PlaceScreen extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, body: SingleChildScrollView( child: Padding( padding: EdgeInsets.all((10)), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ Stack( clipBehavior: Clip.none, children: [ Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height/2, decoration: BoxDecoration( image: DecorationImage( image: AssetImage("images/bg.jpg"), fit: BoxFit.cover ) ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( onTap: (){}, child: Container( margin: EdgeInsets.all(15), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 2, spreadRadius: 4 ) ] ), child: Icon( Icons.arrow_back_ios, color: Colors.red, ), ), ) ], ), ), Positioned( bottom: -30, right:20, child: Container( margin: EdgeInsets.all(15), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(25), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 2, spreadRadius: 4 ) ] ), child: Icon( Icons.favorite_outline, color: Colors.red, size:20 ), ), ) ], ), //***************************** */ // added new code // //************************** */ SizedBox(height: 40,), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Place Title", style: TextStyle( fontSize: 30, fontWeight: FontWeight.w600, color: Colors.red ), ), Text( "View Map", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, color: Colors.green ), ) ], ) ], ), ), ), ), ); } }
6. add paragraph textimport 'package:flutter/material.dart'; class PlaceScreen extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, body: SingleChildScrollView( child: Padding( padding: EdgeInsets.all((10)), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ Stack( clipBehavior: Clip.none, children: [ Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height/2, decoration: BoxDecoration( image: DecorationImage( image: AssetImage("images/bg.jpg"), fit: BoxFit.cover ) ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( onTap: (){}, child: Container( margin: EdgeInsets.all(15), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 2, spreadRadius: 4 ) ] ), child: Icon( Icons.arrow_back_ios, color: Colors.red, ), ), ) ], ), ), Positioned( bottom: -30, right:20, child: Container( margin: EdgeInsets.all(15), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(25), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 2, spreadRadius: 4 ) ] ), child: Icon( Icons.favorite_outline, color: Colors.red, size:20 ), ), ) ], ), SizedBox(height: 40,), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Place Title", style: TextStyle( fontSize: 30, fontWeight: FontWeight.w600, color: Colors.red ), ), Text( "View Map", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, color: Colors.green ), ) ], ), //************************************ */ // added new code // //********************************** */ Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Icon( Icons.favorite_outline ), Text( "4.5 (125 reviews)", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, color: Colors.green ), ) ], ) ], ), ), ), ), ); } }
6. add Facility titleimport 'package:flutter/material.dart'; class PlaceScreen extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, body: SingleChildScrollView( child: Padding( padding: EdgeInsets.all((10)), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Stack( clipBehavior: Clip.none, children: [ Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height/2, decoration: BoxDecoration( image: DecorationImage( image: AssetImage("images/bg.jpg"), fit: BoxFit.cover ) ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( onTap: (){}, child: Container( margin: EdgeInsets.all(15), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 2, spreadRadius: 4 ) ] ), child: Icon( Icons.arrow_back_ios, color: Colors.red, ), ), ) ], ), ), Positioned( bottom: -30, right:20, child: Container( margin: EdgeInsets.all(15), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(25), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 2, spreadRadius: 4 ) ] ), child: Icon( Icons.favorite_outline, color: Colors.red, size:20 ), ), ) ], ), SizedBox(height: 40,), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Place Title", style: TextStyle( fontSize: 30, fontWeight: FontWeight.w600, color: Colors.red ), ), Text( "View Map", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, color: Colors.green ), ) ], ), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Icon( Icons.favorite_outline ), Text( "4.5 (125 reviews)", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, color: Colors.green ), ) ], ), //******************************** */ // added new code // //******************************* */ Text( "Renewal of Sophos Enterprise Guard 3 Year for XG 106 | Need upgrade from the Sophos Enterprise Guard 3 Year for XG 106 to the Sophos XStream Bundle 3 Year for XGS 107 | Serial Number of Sophos Enterprise Guard 3 Year for XG 106 is C1C0B98P4PJYP9C", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, color: Colors.black, ), textAlign: TextAlign.justify, ) ], ), ), ), ), ); } }
7. add image listingimport 'package:flutter/material.dart'; class PlaceScreen extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, body: SingleChildScrollView( child: Padding( padding: EdgeInsets.all((10)), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Stack( clipBehavior: Clip.none, children: [ Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height/2, decoration: BoxDecoration( image: DecorationImage( image: AssetImage("images/bg.jpg"), fit: BoxFit.cover ) ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( onTap: (){}, child: Container( margin: EdgeInsets.all(15), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 2, spreadRadius: 4 ) ] ), child: Icon( Icons.arrow_back_ios, color: Colors.red, ), ), ) ], ), ), Positioned( bottom: -30, right:20, child: Container( margin: EdgeInsets.all(15), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(25), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 2, spreadRadius: 4 ) ] ), child: Icon( Icons.favorite_outline, color: Colors.red, size:20 ), ), ) ], ), SizedBox(height: 40,), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Place Title", style: TextStyle( fontSize: 30, fontWeight: FontWeight.w600, color: Colors.red ), ), Text( "View Map", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, color: Colors.green ), ) ], ), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Icon( Icons.favorite_outline ), Text( "4.5 (125 reviews)", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, color: Colors.green ), ) ], ), Text( "Renewal of Sophos Enterprise Guard 3 Year for XG 106 | Need upgrade from the Sophos Enterprise Guard 3 Year for XG 106 to the Sophos XStream Bundle 3 Year for XGS 107 | Serial Number of Sophos Enterprise Guard 3 Year for XG 106 is C1C0B98P4PJYP9C", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, color: Colors.black, ), textAlign: TextAlign.justify, ), //**************************** */ // added new code // //*************************** */ Text( "Facilities", style: TextStyle( fontSize: 30, fontWeight: FontWeight.w600, color: Colors.red ), ), ], ), ), ), ), ); } } import 'package:flutter/material.dart'; import 'package:a/widgets/build_card.dart'; class PlaceScreen extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.white, body: SingleChildScrollView( child: Padding( padding: EdgeInsets.all((10)), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Stack( clipBehavior: Clip.none, children: [ Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height/2, decoration: BoxDecoration( image: DecorationImage( image: AssetImage("images/bg.jpg"), fit: BoxFit.cover ) ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( onTap: (){}, child: Container( margin: EdgeInsets.all(15), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 2, spreadRadius: 4 ) ] ), child: Icon( Icons.arrow_back_ios, color: Colors.red, ), ), ) ], ), ), Positioned( bottom: -30, right:20, child: Container( margin: EdgeInsets.all(15), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(25), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 2, spreadRadius: 4 ) ] ), child: Icon( Icons.favorite_outline, color: Colors.red, size:20 ), ), ) ], ), SizedBox(height: 40,), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Place Title", style: TextStyle( fontSize: 30, fontWeight: FontWeight.w600, color: Colors.red ), ), Text( "View Map", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, color: Colors.green ), ) ], ), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Icon( Icons.favorite_outline ), Text( "4.5 (125 reviews)", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, color: Colors.green ), ) ], ), Text( "Renewal of Sophos Enterprise Guard 3 Year for XG 106 | Need upgrade from the Sophos Enterprise Guard 3 Year for XG 106 to the Sophos XStream Bundle 3 Year for XGS 107 | Serial Number of Sophos Enterprise Guard 3 Year for XG 106 is C1C0B98P4PJYP9C", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, color: Colors.black, ), textAlign: TextAlign.justify, ), Text( "Facilities", style: TextStyle( fontSize: 30, fontWeight: FontWeight.w600, color: Colors.red ), ), //******************************** */ // added new code /// // ****************************// Row( children: [ BuildCard(title:"test1", rating : "4.5", image: "images/bg.jpg"), BuildCard(title:"test1", rating : "4.5", image: "images/bg.jpg"), BuildCard(title:"test1", rating : "4.5", image: "images/bg.jpg"), ], ) ], ), ), ), ), ); } } widget : BuildCard
widgets/build_card.dart
import 'package:flutter/material.dart'; class BuildCard extends StatelessWidget { final String title; final String rating; final String image; BuildCard({required this.title, required this.rating, required this.image}); @override Widget build(BuildContext context) { return Container(); } } import 'package:flutter/material.dart'; class BuildCard extends StatelessWidget { final String title; final String rating; final String image; BuildCard({required this.title, required this.rating, required this.image}); @override Widget build(BuildContext context) { return Container( child: Column( children: [ Icon( Icons.home ), Text( title ) ], ) ); } }