Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Gperez88/34d8eeeae5b43329476c2a52f3484a11 to your computer and use it in GitHub Desktop.
Save Gperez88/34d8eeeae5b43329476c2a52f3484a11 to your computer and use it in GitHub Desktop.
Flutter Google Maps Bottom Sheet
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