Forked from rohan20/flutter_google_maps_bottom_sheet.dart
Created
July 21, 2024 10:17
-
-
Save untillnesss/1da495e809b9af5ef19d8592073e88c7 to your computer and use it in GitHub Desktop.
Flutter Google Maps Bottom Sheet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
class GoogleMapsClonePage extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
body: Stack( | |
children: <Widget>[ | |
CustomGoogleMap(), | |
CustomHeader(), | |
DraggableScrollableSheet( | |
initialChildSize: 0.30, | |
minChildSize: 0.15, | |
builder: (BuildContext context, ScrollController scrollController) { | |
return SingleChildScrollView( | |
controller: scrollController, | |
child: CustomScrollViewContent(), | |
); | |
}, | |
), | |
], | |
), | |
); | |
} | |
} | |
/// Google Map in the background | |
class CustomGoogleMap extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Container( | |
color: Colors.blue[50], | |
child: Center(child: Text("Google Map here")), | |
); | |
} | |
} | |
/// Search text field plus the horizontally scrolling categories below the text field | |
class CustomHeader extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Column( | |
children: <Widget>[ | |
CustomSearchContainer(), | |
CustomSearchCategories(), | |
], | |
); | |
} | |
} | |
class CustomSearchContainer extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Padding( | |
padding: const EdgeInsets.fromLTRB(16, 40, 16, 8), //adjust "40" according to the status bar size | |
child: Container( | |
height: 50, | |
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(6)), | |
child: Row( | |
children: <Widget>[ | |
CustomTextField(), | |
Icon(Icons.mic), | |
SizedBox(width: 16), | |
CustomUserAvatar(), | |
SizedBox(width: 16), | |
], | |
), | |
), | |
); | |
} | |
} | |
class CustomTextField extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Expanded( | |
child: TextFormField( | |
maxLines: 1, | |
decoration: InputDecoration( | |
contentPadding: const EdgeInsets.all(16), | |
hintText: "Search here", | |
border: InputBorder.none, | |
), | |
), | |
); | |
} | |
} | |
class CustomUserAvatar extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Container( | |
height: 32, | |
width: 32, | |
decoration: BoxDecoration(color: Colors.grey[500], borderRadius: BorderRadius.circular(16)), | |
); | |
} | |
} | |
class CustomSearchCategories extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return SingleChildScrollView( | |
scrollDirection: Axis.horizontal, | |
child: Row( | |
children: <Widget>[ | |
SizedBox(width: 16), | |
CustomCategoryChip(Icons.fastfood, "Takeout"), | |
SizedBox(width: 12), | |
CustomCategoryChip(Icons.directions_bike, "Delivery"), | |
SizedBox(width: 12), | |
CustomCategoryChip(Icons.local_gas_station, "Gas"), | |
SizedBox(width: 12), | |
CustomCategoryChip(Icons.shopping_cart, "Groceries"), | |
SizedBox(width: 12), | |
CustomCategoryChip(Icons.local_pharmacy, "Pharmacies"), | |
SizedBox(width: 12), | |
], | |
), | |
); | |
} | |
} | |
class CustomCategoryChip extends StatelessWidget { | |
final IconData iconData; | |
final String title; | |
CustomCategoryChip(this.iconData, this.title); | |
@override | |
Widget build(BuildContext context) { | |
return Chip( | |
label: Row( | |
children: <Widget>[Icon(iconData, size: 16), SizedBox(width: 8), Text(title)], | |
), | |
backgroundColor: Colors.grey[50], | |
); | |
} | |
} | |
/// Content of the DraggableBottomSheet's child SingleChildScrollView | |
class CustomScrollViewContent extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Card( | |
elevation: 12.0, | |
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), | |
margin: const EdgeInsets.all(0), | |
child: Container( | |
decoration: BoxDecoration( | |
borderRadius: BorderRadius.circular(24), | |
), | |
child: CustomInnerContent(), | |
), | |
); | |
} | |
} | |
class CustomInnerContent extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Column( | |
children: <Widget>[ | |
SizedBox(height: 12), | |
CustomDraggingHandle(), | |
SizedBox(height: 16), | |
CustomExploreBerlin(), | |
SizedBox(height: 16), | |
CustomHorizontallyScrollingRestaurants(), | |
SizedBox(height: 24), | |
CustomFeaturedListsText(), | |
SizedBox(height: 16), | |
CustomFeaturedItemsGrid(), | |
SizedBox(height: 24), | |
CustomRecentPhotosText(), | |
SizedBox(height: 16), | |
CustomRecentPhotoLarge(), | |
SizedBox(height: 12), | |
CustomRecentPhotosSmall(), | |
SizedBox(height: 16), | |
], | |
); | |
} | |
} | |
class CustomDraggingHandle extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Container( | |
height: 5, | |
width: 30, | |
decoration: BoxDecoration(color: Colors.grey[200], borderRadius: BorderRadius.circular(16)), | |
); | |
} | |
} | |
class CustomExploreBerlin extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Row( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
Text("Explore Berlin", style: TextStyle(fontSize: 22, color: Colors.black45)), | |
SizedBox(width: 8), | |
Container( | |
height: 24, | |
width: 24, | |
child: Icon(Icons.arrow_forward_ios, size: 12, color: Colors.black54), | |
decoration: BoxDecoration(color: Colors.grey[200], borderRadius: BorderRadius.circular(16)), | |
), | |
], | |
); | |
} | |
} | |
class CustomHorizontallyScrollingRestaurants extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Padding( | |
padding: const EdgeInsets.only(left: 16), | |
child: SingleChildScrollView( | |
scrollDirection: Axis.horizontal, | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
CustomRestaurantCategory(), | |
SizedBox(width: 12), | |
CustomRestaurantCategory(), | |
SizedBox(width: 12), | |
CustomRestaurantCategory(), | |
SizedBox(width: 12), | |
CustomRestaurantCategory(), | |
SizedBox(width: 12), | |
], | |
), | |
), | |
); | |
} | |
} | |
class CustomFeaturedListsText extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Padding( | |
padding: const EdgeInsets.only(left: 16), | |
//only to left align the text | |
child: Row( | |
children: <Widget>[Text("Featured Lists", style: TextStyle(fontSize: 14))], | |
), | |
); | |
} | |
} | |
class CustomFeaturedItemsGrid extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 16), | |
child: GridView.count( | |
//to avoid scrolling conflict with the dragging sheet | |
physics: NeverScrollableScrollPhysics(), | |
padding: const EdgeInsets.all(0), | |
crossAxisCount: 2, | |
mainAxisSpacing: 12, | |
crossAxisSpacing: 12, | |
shrinkWrap: true, | |
children: <Widget>[ | |
CustomFeaturedItem(), | |
CustomFeaturedItem(), | |
CustomFeaturedItem(), | |
CustomFeaturedItem(), | |
], | |
), | |
); | |
} | |
} | |
class CustomRecentPhotosText extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Padding( | |
padding: const EdgeInsets.only(left: 16), | |
child: Row( | |
children: <Widget>[ | |
Text("Recent Photos", style: TextStyle(fontSize: 14)), | |
], | |
), | |
); | |
} | |
} | |
class CustomRecentPhotoLarge extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 16), | |
child: CustomFeaturedItem(), | |
); | |
} | |
} | |
class CustomRecentPhotosSmall extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return CustomFeaturedItemsGrid(); | |
} | |
} | |
class CustomRestaurantCategory extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Container( | |
height: 100, | |
width: 100, | |
decoration: BoxDecoration( | |
color: Colors.grey[500], | |
borderRadius: BorderRadius.circular(8), | |
), | |
); | |
} | |
} | |
class CustomFeaturedItem extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Container( | |
height: 200, | |
decoration: BoxDecoration( | |
color: Colors.grey[500], | |
borderRadius: BorderRadius.circular(8), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment