Добавление расширяемой боковой панели с помощью NavigationRail во Flutter.

Если это то, чего вы хотите достичь, то этот пост для вас.

Обычно, для мобильного приложения, использование BottomNavigationBar было бы прекрасным. Однако BottomNavigationBar для настольного сайта? Никто так не делает!

Поэтому вот альтернатива.
Представляем NavigationRail, это идеальный виджет для реализации боковой панели в веб-приложении/на десктопе.

1. Где разместить?

Ну, поскольку это боковая панель, то этот виджет будет вставлен в левую или правую часть вашей страницы, и для того, чтобы сделать это, мы будем использовать виджет Row.

class PageWithSideBar extends StatefulWidget {
  const PageWithSideBar({Key? key}) : super(key: key);

  @override
  State<PageWithSideBar> createState() => _PageWithSideBarState();
}

class _PageWithSideBarState extends State<PageWithSideBar> {
  int _selectedIndex = 0;
  final List<String> _destinations = ['Home', 'Calendar', 'Email'];

  Widget _buildNavigationRail() {
    return Container() //TODO: We are going to implement here
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: <Widget>[
          _buildNavigationRail(), // HERE: This is our SideBar
          Expanded(
            child: Center(
              child: Text('This is ${_destinations[_selectedIndex]} Page'),
            ),
          )
        ],
      ),
    );
  }
}


Войти в полноэкранный режим Выход из полноэкранного режима

Обратите внимание, что мы используем виджет Expanded в нашем основном контенте, поэтому он займет как можно больше места.

2. Теперь давайте реализуем NavigationRail.

Widget _buildNavigationRail() {
    return NavigationRail(
      labelType: NavigationRailLabelType.selected,
      selectedIndex: _selectedIndex,
      onDestinationSelected: (int index) {
        setState(() {
          _selectedIndex = index;
        });
      },
      destinations: const <NavigationRailDestination>[
        NavigationRailDestination(
          icon: Icon(Icons.home_outlined),
          selectedIcon: Icon(Icons.home),
          label: Text('Home'),
        ),
        NavigationRailDestination(
          icon: Icon(Icons.calendar_month_outlined),
          selectedIcon: Icon(Icons.calendar_month),
          label: Text('Calendar'),
        ),
        NavigationRailDestination(
          icon: Icon(Icons.email_outlined),
          selectedIcon: Icon(Icons.email),
          label: Text('Email'),
        ),
      ],
    );
  }

Вход в полноэкранный режим Выход из полноэкранного режима

Давайте посмотрим, что получилось.

На мой взгляд, эта боковая панель все еще выглядит как мобильная, так как же сделать ее более похожей на боковую панель сайта?

Мы собираемся сделать это, превратив его в расширяемый сайдбар. Хорошая новость заключается в том, что Flutter Dev точно знает, чего мы хотим, поскольку есть свойство extended, так почему бы нам не установить его значение в «true»?

NavigationRail(
extended: true, 
labelType: NavigationRailLabelType.selected, ...)

Вход в полноэкранный режим Выход из полноэкранного режима

Стоп, здесь есть ошибка. Упоминается, что если мы установим «extended» в true, то мы должны установить labelType в «none».
Ладно, это понятно, так как иметь оба ярлыка внизу и рядом с иконкой было бы очень странно.

NavigationRail(
extended: true,   
labelType: NavigationRailLabelType.none, ...)
Вход в полноэкранный режим Выйдите из полноэкранного режима

Теперь ошибка исчезла

Но, похоже, здесь чего-то не хватает… Это должно быть переключением, так что у нас должно быть что-то вроде иконки меню.

Хорошо, вот мое решение,

  1. Объявите новую булеву переменную _isExtended как свойство NavigationRail.
  2. Добавить AppBar с кнопкой IconButton для переключения состояния _isExtended.

Вот код

class PageWithSideBar extends StatefulWidget {
  const PageWithSideBar({Key? key}) : super(key: key);

  @override
  State<PageWithSideBar> createState() => _PageWithSideBarState();
}

class _PageWithSideBarState extends State<PageWithSideBar> {
  int _selectedIndex = 0;
  final List<String> _destinations = ['Home', 'Calendar', 'Email'];
  bool _isExpanded = false; //NEW VARIABLE
  Widget _buildNavigationRail() {
    return NavigationRail(
      extended: _isExpanded, //NEW VARIABLE
      labelType: NavigationRailLabelType.none,
      selectedIndex: _selectedIndex,
      onDestinationSelected: (int index) {
        setState(() {
          _selectedIndex = index;
        });
      },
      destinations: const <NavigationRailDestination>[
        NavigationRailDestination(
          icon: Icon(Icons.home_outlined),
          selectedIcon: Icon(Icons.home),
          label: Text('Home'),
        ),
        NavigationRailDestination(
          icon: Icon(Icons.calendar_month_outlined),
          selectedIcon: Icon(Icons.calendar_month),
          label: Text('Calendar'),
        ),
        NavigationRailDestination(
          icon: Icon(Icons.email_outlined),
          selectedIcon: Icon(Icons.email),
          label: Text('Email'),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar( //ADDED APP BAR
        title: const Text('Navigation Rails Example'),
        leading: IconButton( 
          icon: const Icon(Icons.menu),
          onPressed: () {
            setState(() {
              _isExpanded = !_isExpanded;
            });
          },
        ),
      ),
      body: Row(
        children: <Widget>[
          _buildNavigationRail(),
          Expanded(
            child: Center(
              child: Text('This is ${_destinations[_selectedIndex]} Page'),
            ),
          )
        ],
      ),
    );
  }
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Вот результаты

Вот полный код

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Navigation Rails Example';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: _title,
      home: PageWithSideBar(),
    );
  }
}

class PageWithSideBar extends StatefulWidget {
  const PageWithSideBar({Key? key}) : super(key: key);

  @override
  State<PageWithSideBar> createState() => _PageWithSideBarState();
}

class _PageWithSideBarState extends State<PageWithSideBar> {
  int _selectedIndex = 0;
  final List<String> _destinations = ['Home', 'Calendar', 'Email'];
  bool _isExpanded = false; 
  Widget _buildNavigationRail() {
    return NavigationRail(
      extended: _isExpanded, 
      labelType: NavigationRailLabelType.none,
      selectedIndex: _selectedIndex,
      onDestinationSelected: (int index) {
        setState(() {
          _selectedIndex = index;
        });
      },
      destinations: const <NavigationRailDestination>[
        NavigationRailDestination(
          icon: Icon(Icons.home_outlined),
          selectedIcon: Icon(Icons.home),
          label: Text('Home'),
        ),
        NavigationRailDestination(
          icon: Icon(Icons.calendar_month_outlined),
          selectedIcon: Icon(Icons.calendar_month),
          label: Text('Calendar'),
        ),
        NavigationRailDestination(
          icon: Icon(Icons.email_outlined),
          selectedIcon: Icon(Icons.email),
          label: Text('Email'),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar( //ADDED APP BAR
        title: const Text('Navigation Rails Example'),
        leading: IconButton( 
          icon: const Icon(Icons.menu),
          onPressed: () {
            setState(() {
              _isExpanded = !_isExpanded;
            });
          },
        ),
      ),
      body: Row(
        children: <Widget>[
          _buildNavigationRail(),
          Expanded(
            child: Center(
              child: Text('This is ${_destinations[_selectedIndex]} Page'),
            ),
          )
        ],
      ),
    );
  }
}

Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь все готово.

Спасибо, что прочитали.

Оцените статью
devanswers.ru
Добавить комментарий