Как создать расширяемый список в навигационном ящике Flutter, который использует одну панель приложений для разных экранов
Мне нужно разработать навигационный ящик во флаттере, и я новичок в флаттере, я использую следующий код, и это создает меню, как и ожидалось, но проблема в том,
1.handling screen navigation
2.maintaining state and navigating back to the screen which is previously opened
Я не могу использовать этот код в виджете с сохранением состояния, так как мне нужно поддерживать состояние панели навигации.
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:skubiq/second_screen.dart';
import 'package:skubiq/third_screen.dart';
class ExpansionList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index) => EntryItem(
data[index],
),
);
}
}
// Welcome to another flutter tutorial
// In this video we will see how to create a multi-level Expansion List
// First Let's create a class for each row in the Expansion List
class Entry {
final String title;
final List<Entry>
children; // Since this is an expansion list ...children can be another list of entries
Entry(this.title, [this.children = const <Entry>[]]);
}
// This is the entire multi-level list displayed by this app
final List<Entry> data = <Entry>[
Entry(
'Chapter A',
<Entry>[
Entry('Section A0',
// <Entry>[
// Entry('Item A0.1'),
// Entry('Item A0.2'),
// Entry('Item A0.3'),
// ],
),
Entry('Section A1'),
Entry('Section A2'),
],
),
// Second Row
Entry('Chapter B', <Entry>[
Entry('Section B0'),
Entry('Section B1'),
]),
Entry(
'Chapter C',
<Entry>[
Entry('Section C0'),
Entry('Section C1'),
Entry(
'Section C2',
<Entry>[
Entry('Item C2.0'),
Entry('Item C2.1'),
Entry('Item C2.2'),
Entry('Item C2.3'),
],
)
],
),
];
// Create the Widget for the row
class EntryItem extends StatelessWidget {
const EntryItem(this.entry);
final Entry entry;
// This function recursively creates the multi-level list rows.
Widget _buildTiles(Entry root) {
if (root.children.isEmpty) {
return ListTile(
title: Text(root.title),
onTap: (){
Fluttertoast.showToast(msg: root.title);
_getDrawerItemWidget(root.title);
},
);
}
return ExpansionTile(
key: PageStorageKey<Entry>(root),
title: Text(root.title),
children: root.children.map<Widget>(_buildTiles).toList(),
);
}
@override
Widget build(BuildContext context) {
return Container(
child: _buildTiles(entry));
}
_getDrawerItemWidget(String screenName) {
switch (screenName) {
case "Section A0":
return new ThirdScreen();
case "Section A1":
return new SecondScreen();
case "Section A2":
return new ThirdScreen();
default:
return new Text("Error");
}
}
}
По сути, я разработчик приложений для Android. Я с нетерпением жду реализации следующей концепции, такой как однократная активность с навигационным ящиком и обработка нескольких фрагментов в флаттере.
Пожалуйста, помогите мне выполнить требование
Любые предложения исходного кода или полностью реализованный код полезны для моих нужд.
1 ответ
Наконец, здесь никто не ответил, и я работаю и нахожу решение своей проблемы.
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:skubiq/Constants/app_constants_ui.dart';
import 'package:skubiq/ModelClasses/nav_drawer_menu_entries.dart';
import 'package:skubiq/Widgets/custom_appbar.dart';
import 'package:skubiq/screens/home_screen.dart';
import 'package:skubiq/screens/second_screen.dart';
import 'package:skubiq/screens/first_screen.dart';
import 'package:skubiq/screens/third_screen.dart';
import '../Constants/string_const.dart';
class NavDrawer extends StatefulWidget with PreferredSizeWidget {
@override
State<StatefulWidget> createState() {
return new NavDrawerState();
}
@override
// TODO: implement preferredSize
Size get preferredSize => throw UnimplementedError();
}
class NavDrawerState extends State<NavDrawer> {
int _selectedDrawerIndex = 0;
String screenName = "Home";
final ScrollController scroll = ScrollController();
@override
void dispose() {
scroll.dispose();
super.dispose();
}
_getDrawerItemWidget(String pos) {
switch (pos) {
case "Home":
return new HomeScreen();
case "Receiving":
return new FirstScreen();
case "Putaway":
return new SecondScreen();
case "Pallet Transfer":
return new ThirdScreen();
default:
return new Text("Error");
}
}
_onSelectItem(String screen) {
setState(() => screenName = screen);
Navigator.of(context).pop(); // close the drawer
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
// here we display the title corresponding to the fragment
// you can instead choose to have a static title
child: Text(screenName),
context: context,
),
drawer: Drawer(
child: Container(
decoration: AppConstants.customBoxDecoration,
//you can use your own boxdecoration
child: Column(
children: <Widget>[
UserAccountsDrawerHeader(
decoration: AppConstants.customBoxDecoration,
currentAccountPicture: new CircleAvatar(
radius: 60.0,
// backgroundColor: const Color(0xFF778899),
backgroundImage: AssetImage('assets/logo.png'),
),
accountName: new Text("Name"),
accountEmail: new Text("mail")),
Flexible(
child: ListView.builder(
shrinkWrap: true,
controller: scroll,
itemCount: StringConstants.menuList.length,
itemBuilder: (BuildContext context, int index) => buildList(
StringConstants.menuList[index],
))
)
],
),
)),
body: _getDrawerItemWidget(screenName),
);
}
// This function recursively creates the multi-level list rows.
Widget _buildTiles(Entry root) {
if (root.children.isEmpty) {
return ListTile(
leading: Icon(root.icon),
title: Text(
root.title,
style: AppConstants.textStyleNavDrawer,
),
onTap: () {
Fluttertoast.showToast(msg: root.title);
_onSelectItem(root.title);
},
);
}
return ExpansionTile(
key: PageStorageKey<Entry>(root),
maintainState: true,
title: Text(
root.title,
style: AppConstants.textStyleNavDrawer,
),
children: root.children.map<Widget>(_buildTiles).toList(),
);
}
Widget buildList(Entry entry) {
return _buildTiles(entry);
}
}
Пользовательский класс панели приложений
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:skubiq/Constants/app_constants_ui.dart';
import 'package:skubiq/Constants/custom_colors.dart';
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
final Widget child;
final double height;
final BuildContext context;
CustomAppBar(
{required this.child,
this.height = kToolbarHeight,
required this.context});
@override
Size get preferredSize => Size.fromHeight(height);
@override
Widget build(BuildContext context) {
return AppBar(
title: child,
flexibleSpace: Container(
decoration: AppConstants.customBoxDecoration,
),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.qr_code_scanner,
color: Colors.white,
),
onPressed: () {
Fluttertoast.showToast(msg: context.toString());
// do something
},
)
],
);
}
}
Класс констант приложения
import 'package:flutter/material.dart';
import 'package:skubiq/Constants/custom_colors.dart';
class AppConstants {
static const BoxDecoration customBoxDecoration = BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [CustomColors.iconSplashColor, CustomColors.iconColor]));
// you define your own colors
static const TextStyle textStyleNavDrawer = TextStyle(
color: Colors.white);
}
Попробуйте этот пример, если вам нужна одна панель приложений для разных экранов.