skip to Main Content

I wish to place a mini button on the left side of the body of the app screen to be used to open a mini drawer in Flutter. To be able to figure it out, I prepared the following image:

enter image description here

As seen, when the user taps on the mini button, a mini drawer-like panel comes in and when the user clicks again on the same button, it closes the panel.

Thank you

2

Answers


  1. You can create your own widget like in the following example.

    import 'dart:math';
    
    import 'package:flutter/material.dart';
    
    class MiniDrawer extends StatefulWidget {
      final Widget child;
      final Widget drawerContent;
      final Duration animationDuration;
      final Size drawerSize;
      final Size drawerButtonSize;
      final Color background;
      final Color iconColor;
    
      const MiniDrawer({
        super.key,
        required this.child,
        required this.drawerContent,
        this.iconColor = Colors.white,
        this.background = const Color.fromRGBO(255, 120, 0, 1),
        this.drawerSize = const Size(250, 300),
        this.drawerButtonSize = const Size(50, 90),
        this.animationDuration = const Duration(milliseconds: 200),
      });
    
      @override
      State<MiniDrawer> createState() => _MiniDrawerState();
    }
    
    class _MiniDrawerState extends State<MiniDrawer> {
      bool _isOpen = false;
    
      @override
      Widget build(BuildContext context) {
        return LayoutBuilder(builder: (context, constraints) {
          return Stack(
            clipBehavior: Clip.none,
            children: [
              widget.child,
              _buildDrawer(constraints),
            ],
          );
        });
      }
    
      Widget _buildDrawer(BoxConstraints constraints) {
        return AnimatedPositioned(
          duration: widget.animationDuration,
          top: constraints.maxHeight / 2 - widget.drawerSize.height / 2,
          left: _isOpen ? 0 : min(-widget.drawerSize.width, constraints.maxWidth),
          child: SizedBox(
            height: widget.drawerSize.height,
            width: widget.drawerSize.width + widget.drawerButtonSize.width,
            child: Stack(
              alignment: Alignment.centerRight,
              clipBehavior: Clip.none,
              children: [
                _buildDrawerBtn(),
                Row(
                  children: [
                    Expanded(
                      child: SingleChildScrollView(
                        child: Container(
                          constraints: BoxConstraints(minHeight: widget.drawerButtonSize.height),
                          color: widget.background,
                          child: widget.drawerContent,
                        ),
                      ),
                    ),
                    SizedBox(width: widget.drawerButtonSize.width),
                  ],
                ),
              ],
            ),
          ),
        );
      }
    
      Widget _buildDrawerBtn() {
        Radius radius = Radius.circular(widget.drawerButtonSize.height / 2);
        return Positioned(
          right: 10,
          child: GestureDetector(
            onTap: () {
              setState(() {
                _isOpen = !_isOpen;
              });
            },
            child: Container(
              decoration: BoxDecoration(
                color: widget.background,
                borderRadius: BorderRadius.only(
                  topRight: radius,
                  bottomRight: radius,
                ),
              ),
              width: widget.drawerButtonSize.width,
              height: widget.drawerButtonSize.height,
              child: AnimatedRotation(
                duration: widget.animationDuration,
                turns: _isOpen ? 0.5 : 0,
                child: Icon(
                  Icons.chevron_right,
                  size: 32,
                  color: widget.iconColor,
                ),
              ),
            ),
          ),
        );
      }
    }
    

    And then you can use that widget in your code like this.

    @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: const Text('app bar')),
          body: MiniDrawer(
            drawerContent: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: List.generate(
                  10,
                  (index) => ListTile(
                    title: Text('Item $index'),
                  ),
                ),
              ),
            ),
            child: const Column(
              children: [
                Text('Page content'),
              ],
            ),
          ),
        );
      }
    
    Login or Signup to reply.
  2. This code will allow you to use the endDrawer as your mini drawer, and your main drawer will be there as well.

    You can look on the web to customize the end drawer’s UI as per your needs.

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MainApp());
    }
    
    class MainApp extends StatelessWidget {
      const MainApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          home: Scaffold(
            body: TwoDrawers(),
          ),
        );
      }
    }
    
    class TwoDrawers extends StatelessWidget {
      const TwoDrawers({super.key});
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text("Mini Drawer"),
            actions: const [SizedBox()],
          ),
          drawer: Drawer(
            child: Container(
              color: Colors.blue,
              child: const Center(
                child: Text(
                  "Main Drawer",
                  style: TextStyle(color: Colors.white, fontSize: 30),
                ),
              ),
            ),
          ),
          endDrawer: SizedBox(
            height: 300,
            child: Drawer(
              elevation: 0,
              backgroundColor: Colors.indigo,
              child: Row(
                children: [
                  IconButton(
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                    icon: const Icon(Icons.chevron_right),
                    color: Colors.white,
                  ),
                  Container(
                    width: 240,
                    color: Colors.indigo,
                    child: const Center(
                      child: Text(
                        "Mini Drawer",
                        style: TextStyle(color: Colors.white, fontSize: 30),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
          body: Stack(
            children: [
              Positioned(
                height: 40,
                top: 250,
                right: -30,
                child: SizedBox(
                  child: Builder(
                    builder: (context) {
                      return ElevatedButton(
                        style: ButtonStyle(
                          backgroundColor:
                              const MaterialStatePropertyAll(Colors.indigo),
                          shape: MaterialStatePropertyAll(
                            RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(10),
                            ),
                          ),
                          padding: const MaterialStatePropertyAll(
                            EdgeInsets.only(right: 30),
                          ),
                        ),
                        onPressed: () {
                          Scaffold.of(context).openEndDrawer();
                        },
                        child: const Icon(Icons.chevron_left),
                      );
                    },
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    

    Some snapshots:

    Screen Main Drawer Mini Drawer
    screen main drawer mini drawer
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search