Если это то, чего вы хотите достичь, то этот пост для вас.
Обычно, для мобильного приложения, использование 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, ...)
Теперь ошибка исчезла
Но, похоже, здесь чего-то не хватает… Это должно быть переключением, так что у нас должно быть что-то вроде иконки меню.
Хорошо, вот мое решение,
- Объявите новую булеву переменную _isExtended как свойство NavigationRail.
- Добавить 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'),
),
)
],
),
);
}
}
Теперь все готово.
Спасибо, что прочитали.