Hey 👋!
Are you looking for Draggable bottom sheet in flutter? Then you have landed at the right place.
First of all let's see how does Draggable bottom sheet look like
Let's code the approach and the divide the whole section in small chunks of steps
Step 1: Code the boilerplate code
Declare a global boolean variable named as isSwipeUp, initialize with false
import 'package:flutter/material.dart';
bool isSwipeUp =false;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Home(),
);
}
}
Step 2: Write code for home page
Creating Home() as StatefulWidget
As we are placing on widget on other widget so we our using Stack()
In stack element are placed one on other, last element will be on top.
In Stack(), We will use two different Widgets :
MainScreen()
CustomBottomSheet()
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return SafeArea(
child: Scaffold(
body: Container(
color: Colors.black26,
height: size.height,
width: size.width,
child: Stack(
children: [
MainPage(), // [Will create in next step]
Positioned(
top: size.height * 0.8, //position to be changed
child: const CustomBottomSheet() // [Will create in next step]
)
],
),
),
),
);
}
}
Step 3: Create MainScreen()
MainScreen will be very simple as it has only one Container() with a single child with Text() => "HomePage" with some sort of styling and center Alignment
class MainPage extends StatelessWidget {
const MainPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.amber,
child: const Center(child: Text("HomePage",style: TextStyle(color: Colors.white,fontSize: 22),),),
);
}
}
Let's jump to next step
Step 4: Creating CustomBottomSheet()
CustomBottomSheet has a Container(), having full width and half height of screen with rounded corner at top edges and some sort of styling.
class CustomBottomSheet extends StatefulWidget {
const CustomBottomSheet({Key? key}) : super(key: key);
@override
State<CustomBottomSheet> createState() => _CustomBottomSheetState();
}
class _CustomBottomSheetState extends State<CustomBottomSheet> {
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Container(
height: size.height * 0.5,
width: size.width,
decoration: const BoxDecoration(
gradient: LinearGradient(colors: [
Color.fromRGBO(26, 41, 128, 100),
Color.fromRGBO(42, 178, 252, 100),
]),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50), topRight: Radius.circular(50))),
child: Align(alignment: Alignment.topCenter,
child: (isSwipeUp)
? Icon(
Icons.expand_more_outlined,
size: 30,
color: Colors.white,
)
: Icon(
Icons.expand_less_outlined,
size: 30,
color: Colors.white,
),
),
);
}
}
Now at this stage of our App looks like
Step 5: Adding GestureDetector on CustomBottomSheet() for making it Draggable.
Now we have to detect gesture of dragging/ Swiping
But Don't take worries as flutter have an awesome widget GestureDetector()
GestureDetector() helps to detect any kind of gesture on Widget and has various properties but we will use some only.
Adding GestureDetector() on CustomBottomSheet() in Stack
GestureDetector(
onPanEnd: (details) {
print(details.velocity.pixelsPerSecond.dy.toString());
print(details.velocity.pixelsPerSecond.dx.toString());
if (details.velocity.pixelsPerSecond.dy > -100) {
setState(() {
isSwipeUp = true;
});
}
else {
setState(() {
isSwipeUp = false;
});
}
},
child: const CustomBottomSheet())
Now changing position of CustomBottomSheet() as isSwipeUp changes
As the transition should be smooth so we will replace Positioned() to AnimatedPositioned() with duration 400 milliseconds
Positioned➡➡ AnimatedPositioned
top: !isSwipeUp? size.height *0.5:size.height * 0.8,
whole components looks like:-
AnimatedPositioned(
curve: Curves.decelerate,
duration: const Duration(milliseconds: 400),
top: !isSwipeUp? size.height *0.5:size.height * 0.8,
child: GestureDetector(
onPanEnd: (details) { print(details.velocity.pixelsPerSecond.dy.toString());
if (details.velocity.pixelsPerSecond.dy > -100) {
setState(() {
isSwipeUp = true;
});
} else {
setState(() {
isSwipeUp = false;
});
}
},
child: const CustomBottomSheet())
)
Our task is completed🙌🙌.
Catch me on LinkedIn
Top comments (0)