Can anyone advise me how to design a very specific Side menu in flutter.
It has 2 states
When collapsed it is like a Navigation rail. Only icons visible.
But when expanded, it should behave like Navigation drawer. It should blur the rest of the screen, and on click outside of it it should collapse back.
I would appreciate any help. Thank you
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
bool is_expanded = false;
int selectedPage = 1;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: Row(
children: [
Stack(
children: <Widget>[
Container(
color: Colors.transparent,
margin: EdgeInsets.only(left: 120),
width: MediaQuery.of(context).size.width - 120,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 1, sigmaY: 1),
child: Opacity(
opacity: is_expanded ? 0.3 : 1,
child: Listener(
onPointerDown: (v) {
if (is_expanded) {
is_expanded = false;
setState(() {});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Click blocked'),
),
);
}
},
child: AbsorbPointer(
absorbing: is_expanded,
child: Row(
children: [
Expanded(
child: Container(
color: Colors.white,
child: PageHolder(selectedPage),
),
),
],
),
),
),
),
),
),
AnimatedContainer(
duration: Duration(milliseconds: 120),
height: double.infinity,
width: is_expanded ? 240 : 120,
color: Colors.blueGrey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 20),
Row(
mainAxisSize: MainAxisSize.min,
children: const [
Text(
'Custom drawer',
style: TextStyle(
color: Colors.white,
),
),
],
),
const SizedBox(height: 20),
InkWell(
onTap: () {
setState(() => is_expanded = !is_expanded);
},
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"App",
style: TextStyle(
color: Colors.white,
),
),
Icon(
is_expanded ? Icons.arrow_right : Icons.arrow_left,
color: Colors.white,
)
],
),
),
const SizedBox(height: 20),
InkWell(
onTap: () {
selectedPage = 1;
is_expanded = false;
setState(() {});
},
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
"Page 1",
style: TextStyle(
color: Colors.white,
),
),
],
),
),
const SizedBox(height: 20),
InkWell(
onTap: () {
selectedPage = 2;
is_expanded = false;
setState(() {});
},
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
"Page 2",
style: TextStyle(
color: Colors.white,
),
),
],
),
),
],
),
),
],
),
],
),
);
}
PageHolder(selectedPage) {
switch (selectedPage) {
case 1:
{
return Page1();
}
case 2:
{
return Page2();
}
default:
{
return Page1();
}
}
}
}
class Page1 extends StatefulWidget {
const Page1({Key? key}) : super(key: key);
@override
State<Page1> createState() => _Page1State();
}
class _Page1State extends State<Page1> {
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Page 1 content',
style: TextStyle(fontSize: 32),),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Test click'),
),
);
},
child: const Text('Test click'))
],
),
);
}
}
class Page2 extends StatefulWidget {
const Page2({Key? key}) : super(key: key);
@override
State<Page2> createState() => _Page2State();
}
class _Page2State extends State<Page2> {
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Page 2 content',
style: TextStyle(fontSize: 32),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Test click'),
),
);
},
child: const Text('Test click'))
],
),
);
}
}```
Solution ^^
include NavigationRail widget in IntrinsicWidth widget
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
),
drawer: _NavigationRailExample(),
body: Container(),
);
}
}
class _NavigationRailExample extends StatefulWidget {
const _NavigationRailExample({Key? key}) : super(key: key);
_NavigationRailExampleState createState() => _NavigationRailExampleState();
}
class _NavigationRailExampleState extends State<_NavigationRailExample> {
int _selectedIndex = 0;
bool extended =false;
Widget build(BuildContext context) {
return SafeArea(
child: IntrinsicWidth(
child: NavigationRail(
selectedIndex: _selectedIndex,
destinations: _buildDestinations(),
extended: extended,
onDestinationSelected: (int index) {
setState(() {
_selectedIndex = index;
});
},
),
),
);
}
List<NavigationRailDestination> _buildDestinations() {
return [
NavigationRailDestination(
icon: InkWell(
onTap: () {
setState(() =>
extended = !extended);
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text("App"),
Icon(extended ? Icons.arrow_right : Icons.arrow_left)
],
),
),
label: Container(width: 0,) ,
),
NavigationRailDestination(
icon: Icon(Icons.home),
label: Text('Home'),
),
NavigationRailDestination(
icon: Icon(Icons.favorite),
label: Text('Favorites'),
),
NavigationRailDestination(
icon: Icon(Icons.logout),
label: Text('Logout'),
),
];
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With