Como fazer um menu lateral em um Flutter

Tempo de leitura: 4 minutes

O widget Drawer (material library import ‘package:flutter/material.dart’ ) recebe um parâmetro child, que é um widget que aparece na parte superior do menu, geralmente como um título ou cabeçalho. O parâmetro chield geralmente é um widget DrawerHeader, que fornece um espaço para exibir um título ou logotipo.

Código

Drawer Drawer({
  Key? key,
  Color? backgroundColor,
  double? elevation,
  Color? shadowColor,
  Color? surfaceTintColor,
  ShapeBorder? shape,
  double? width,
  Widget? child,
  String? semanticLabel,
})

O widget Drawer também usa widgets ListView ou Column of ListTile como seu conteúdo principal. Cada ListTile representa um item de menu e a propriedade onTap do ListTile pode ser usada para lidar com a interação do usuário quando o item de menu é selecionado.

Para criar um menu lateral em um aplicativo Flutter, você pode usar o widget Drawer da seguinte maneira:

  1. Adicione o widget Scaffold ao método de construção de sua tela, que fornecerá a estrutura básica para sua tela.
  2. Dentro do Scaffold, adicione um widget AppBar à propriedade appBar. Isso criará a barra de aplicativos na parte superior da tela.
  3. Dentro do Scaffold, adicione um widget Drawer à propriedade da gaveta. Isso criará o menu lateral.
  4. Dentro do Drawer, adicione um widget Column com seus itens de menu como widgets ListTile.
  5. Na propriedade onTap de cada ListTile, adicione o código para navegar até a tela correspondente ou execute a ação apropriada.
  6. UserAccountsDrawerHeader – mostra as informações do usuário no cabeçalho do menu lateral.

Barra superior do menu (DrawerHeader)

Code(DrawerHeader)

Container(
     child: UserAccountsDrawerHeader(
            decoration: BoxDecoration(
              color: WidgetColors.mainHeaderColor,
            ),
            accountName: InkWell(
              onTap: () {},
              child: Text.rich(
                TextSpan(
                  children: [
                    TextSpan(
                      text: myAccountName ?? 'NA',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 24.0,
                      ),
                    ),
                    TextSpan(text: ' '),
                  ],
                ),
              ),
            ),
            accountEmail: Text(myGroupType),
            currentAccountPicture: InkWell(
              onTap: () {
                Navigator.of(context).push(MaterialPageRoute(
                    builder: (_) => EditProfileImage(
                          nameInfo: myAccountName.toString(),
                        )));
              },
              child: Stack(
                children: <Widget>[
                  Container(
                    width: 250,
                    height: 250,
                    child: CircleAvatar(
                      backgroundColor: AppTheme.mainColor,
                      radius: 43,
                      child: ClipOval(
                        child: FadeInImage(
                          fadeInDuration: const Duration(milliseconds: 500),
                          placeholder:
                              const AssetImage('assets/images/userL.png'),
                          image: vThumbImage == null
                              ? NetworkImage(
                                  "https://img.icons8.com/fluency/48/null/no-image.png")
                              : NetworkImage(vThumbImage!),
                          imageErrorBuilder: (context, error, stackTrace) {
                            return Container(
                                child: Image.asset("assets/images/userL.png"));
                          },
                          fit: BoxFit.cover,
                          height: 70,
                          width: 70,
                        ),
                      ),
                    ),
                  ),
                  Positioned(
                      bottom: 1,
                      right: 1,
                      child: Container(
                        height: 35,
                        width: 35,
                        child: InkWell(
                          child: const Icon(
                            Icons.add_a_photo,
                            size: 15.0,
                            color: Color(0xFF404040),
                          ),
                        ),
                        decoration: const BoxDecoration(
                            color: Colors.white,
                            borderRadius:
                                BorderRadius.all(Radius.circular(20))),
                      ))
                ],
              ),
            ),
          )),

Código final

Drawer(
   child: ListView(
        padding: EdgeInsets.zero,
        children: <Widget>[
          //------------user image section  and other deatils //
          Container(
              child: UserAccountsDrawerHeader(
            decoration: BoxDecoration(
              color: WidgetColors.mainHeaderColor,
            ),
            accountName: InkWell(
              onTap: () {},
              child: Text.rich(
                TextSpan(
                  children: [
                    TextSpan(
                      text: myAccountName ?? 'NA',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 24.0,
                      ),
                    ),
                    TextSpan(text: ' '),
                  ],
                ),
              ),
            ),
            accountEmail: Text('yourEmail@gmail.com'),
            currentAccountPicture: InkWell(
              onTap: () {
                //-your action
              },
              child: Stack(
                children: <Widget>[
                  Container(
                    width: 250,
                    height: 250,
                    child: CircleAvatar(
                      backgroundColor: AppTheme.mainColor,
                      radius: 43,
                      child: ClipOval(
                        child: FadeInImage(
                          fadeInDuration: const Duration(milliseconds: 500),
                          placeholder:
                              const AssetImage('assets/images/userL.png'),
                          image: vThumbImage == null
                              ? NetworkImage(
                                  "https:xxxx/no-image.png")
                              : NetworkImage(vThumbImage!),
                          imageErrorBuilder: (context, error, stackTrace) {
                            return Container(
                                child: Image.asset("assets/images/userL.png"));
                          },
                          fit: BoxFit.cover,
                          height: 70,
                          width: 70,
                        ),
                      ),
                    ),
                  ),
                  Positioned(
                      bottom: 1,
                      right: 1,
                      child: Container(
                        height: 35,
                        width: 35,
                        child: InkWell(
                          //  onTap: _onAlertPress,
                          child: const Icon(
                            Icons.add_a_photo,
                            size: 15.0,
                            color: Color(0xFF404040),
                          ),
                        ),
                        decoration: const BoxDecoration(
                            color: Colors.white,
                            borderRadius:
                                BorderRadius.all(Radius.circular(20))),
                      ))
                ],
              ),
            ),
          )),
          //--------menu list ------------------//
          ListTile(
            leading: Icon(Icons.home),
            title: Text(
              'side_MenuHome'.tr,
              style: TextStyle(
                fontSize: 15.0,
                color: Colors.black,
                letterSpacing: 0,
              ),
            ),
            onTap: () => selectedItem(context, 0),
          ),
          ListTile(
            leading: Icon(Icons.history_rounded),
            title: Text(
              'side_MenuOrderHistory'.tr,
              style: TextStyle(
                fontSize: 15.0,
                color: Colors.black,
                letterSpacing: 0,
              ),
            ),
            onTap: () => selectedItem(context, 1),
          ),
          ListTile(
            leading: Icon(Icons.payment),
            title: Text(
              'side_MenuPaymentHistory'.tr,
              style: TextStyle(
                fontSize: 15.0,
                color: Colors.black,
                letterSpacing: 0,
              ),
            ),
            onTap: () => selectedItem(context, 2),
          ),
          ListTile(
            leading: Icon(
              Icons.settings,
              color: Colors.black54,
            ),
            title: Text(
              'side_MenuSettings'.tr,
              style: TextStyle(
                fontSize: 15.0,
                color: Colors.black,
                letterSpacing: 0,
              ),
            ),
            onTap: () => selectedItem(context, 3),
          ),
          ListTile(
            leading: Image.asset(
              "assets/images/location.png",
              width: 25,
              height: 25,
              fit: BoxFit.fill,
              color: Colors.black54,
            ),
            title: Text(
              'side_MenuChooseLocation'.tr,
              style: TextStyle(
                fontSize: 15.0,
                color: Colors.black,
                letterSpacing: 0,
              ),
            ),
            onTap: () => selectedItem(context, 4),
          ),
          ListTile(
            leading: Image.asset(
              "assets/images/complain.png",
              width: 25,
              height: 25,
              fit: BoxFit.fill,
              color: Colors.black54,
            ),
            title: Text(
              "Support",
              style: TextStyle(
                fontSize: 15.0,
                color: Colors.black,
                letterSpacing: 0,
              ),
            ),
            onTap: () => selectedItem(context, 5),
          ),
          ListTile(
            leading: Image.asset(
              "assets/images/feedback.png",
              width: 25,
              height: 25,
              fit: BoxFit.fill,
              color: Colors.black54,
            ),
            title: Text(
              "Feedback",
              style: TextStyle(
                fontSize: 15.0,
                color: Colors.black,
                letterSpacing: 0,
              ),
            ),
            onTap: () => selectedItem(context, 6),
          ),
          ListTile(
            leading: Icon(Icons.update),
            title: Text(
              'side_MenuUpdate'.tr,
              style: TextStyle(
                fontSize: 15.0,
                color: Colors.black,
                letterSpacing: 0,
              ),
            ),
            onTap: () {
              Fluttertoast.showToast(
                  msg: "Currently no updates available!",
                  toastLength: Toast.LENGTH_SHORT,
                  gravity: ToastGravity.BOTTOM,
                  timeInSecForIosWeb: 1,
                  backgroundColor: AppTheme.mainTextColor,
                  textColor: Colors.white,
                  fontSize: 16.0);

              print("update Click");
            },
          ),
          Divider(
            color: Colors.black38,
          ),
          ListTile(
            leading: Image.asset(
              "assets/images/logout.png",
              width: 25,
              height: 25,
              fit: BoxFit.fill,
              color: Colors.black54,
            ),
            title: Text('side_MenuLogout'.tr),
            onTap: () async {
              showDialog(
                  context: context,
                  builder: (context) {
                    return AlertDialog(
                      title: Text('Logout'), 
                      content: Text('side_MenuLogoutMessage'.tr),
                      actions: <Widget>[
                        TextButton(
                            onPressed: () => Navigator.of(context).pop(),
                            child: Text(
                              'side_MenuLogoutNo'.tr,
                              style: TextStyle(color: Colors.red),
                            )),
                        TextButton(
                          onPressed: () async {
                            SharedPreferences prefs =
                                await SharedPreferences.getInstance();
                         
                            var groupId = prefs.getString('groupId') ?? '';
                            var userId = prefs.getString('userId') ?? '';
                            var password = prefs.getString('password') ?? '';

                            await prefs.remove("accountId");
                            await prefs.remove("AccountName");

                            Navigator.pushAndRemoveUntil(
                                context,
                                MaterialPageRoute(
                                    builder: (BuildContext context) =>
                                        LoginNewPro(groupId, userId, password)),
                                ModalRoute.withName('/'));
                          },
                          child: Text(
                            'side_MenuLogoutYes'.tr,
                            style: TextStyle(color: Colors.red),
                          ),
                        ),
                      ],
                    );
                  });
            },
          ),
              //----------------------end code-------------------//
        ],
      ),
    );
  }

Quando o usuário toca em um item de menu, navegamos para a tela correspondente usando o widget Navigator. Usamos o método pushReplacement para substituir a tela atual pela nova tela e exibir a tela anterior.

void selectedItem(BuildContext context, int index) {
    // Navigator.of(context).pop();
    print(index);
   
    switch (index) {
      case 0:
        Navigator.pushReplacementNamed(context, "/home");
        break;
      case 1:
        Navigator.pushReplacementNamed(context, "/profile");
        break;
      case 2:
        Navigator.pushReplacementNamed(
            context, "/marketOrderHistory");  
        break;
      case 3:
        Navigator.pushReplacementNamed(context, "/paymenthistory");
        break;
      case 4:
        Navigator.pushReplacementNamed(context, "/paymentdeatils");
        break;
      case 5:
        Navigator.pushReplacementNamed(context, "/settings");
        break;
      case 6:
        Navigator.pushReplacementNamed(context, "/chooseLocation");
        break;
      case 7:
        Navigator.pushReplacementNamed(context, "/feedback");
        break;
      case 8:
        Navigator.pushReplacementNamed(context, "/contactus");
        break;
    }
  }

 

Conclusão

Assim, aprendemos como fazer um menu lateral no Flutter, foi feito menu lateral de forma simples. Este exemplo acima ajuda seu próximo projeto a vincular e criar rapidamente e aproveitar se houver algum problema, comente e sinta-se à vontade para entrar em contato conosco a qualquer momento.