链接到github上的来源:https://github.com/dnn1s/flutter_navigationtest
我希望完成与Google对Play商店应用程序相同的导航方法:抽屉列出可用的" root"视图(在我的例子中,view1到view3),而任何根视图都可以有任意数量的子视图和自己的导航堆栈。问题是:即使用户在其中一个子视图上,仍然可以使用滑动手势访问抽屉,从屏幕的左外侧开始并前往中心 - 这是我目前的方法无法实现的。对于Play商店应用,当您点按应用以查看其详细信息时,您可以通过点击左上角的箭头返回或直接通过滑动调用抽屉。
main.dart:没有什么花哨的
void main() => runApp(new NavigationTestApp());
class NavigationTestApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Navigation test',
home: new MainPage(),
);
}
}
mainpage.dart:此视图包含抽屉及其项目
import 'package:flutter/material.dart';
import 'view1.dart';
import 'view2.dart';
import 'view3.dart';
/// just a wrapper class for drawer items; in my original code, these include
/// icons and other properties
class DrawerItem {
String title;
DrawerItem({this.title});
}
class MainPage extends StatefulWidget {
/// list of items in the drawer
final drawerItems = [
new DrawerItem(title: 'Item 1'),
new DrawerItem(title: 'Item 2'),
new DrawerItem(title: 'Item 3')
];
@override
State<MainPage> createState() => new MainPageState();
}
class MainPageState extends State<MainPage> {
int _selectedPageIndex = 0;
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
/// dynamic title, depending on the current view
title: new Text(widget.drawerItems[_selectedPageIndex].title),
),
drawer: new Drawer(
child: new ListView(
padding: EdgeInsets.zero,
children: <Widget>[
new DrawerHeader(child: new Text('Drawer header')),
/// quick and easy way to create the items;
/// in the original
/// code, these items are built in a loop
_buildDrawerItem(0),
_buildDrawerItem(1),
_buildDrawerItem(2),
],
)
),
body: _buildCurrentPage()
);
}
Widget _buildCurrentPage() {
switch(_selectedPageIndex) {
case 0: return new View1();
case 1: return new View2();
case 2: return new View3();
}
return new Text('Invalid page index');
}
Widget _buildDrawerItem(int index) {
return new ListTile(
title: new Text(widget.drawerItems[index].title),
selected: _selectedPageIndex == index,
onTap: () => _handleSelection(index),
);
}
void _handleSelection(int index) {
setState(() {
_selectedPageIndex = index;
});
/// close the drawer
Navigator.of(context).pop();
}
}
这是第一个根视图:
view1.dart:
class View1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new RaisedButton(
child: new Text('Push Subview1'),
onPressed: () {
Navigator.of(context).push(new MaterialPageRoute(
builder: (context) {
return new SubView1();
}
));
},
);
}
}
subview1.dart:
import 'package:flutter/material.dart';
class SubView1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('SubView1'),
),
body: new Text('Pushed from View1')
);
}
}
我知道Cupertino课程,但我更喜欢材料设计。有人能指出我如何实现所需行为的正确方向吗?
答案 0 :(得分:0)
由于它们是两个不同的页面,因此一页中的抽屉将无法在另一页中使用。如果你确实想要,你应该在两个页面中创建抽屉。我已经在一个名为drawer.dart
的单独的类中尽可能多地包装了所有关于Drawer的内容,并且在任何地方都有注释,这样有助于理解。
<强> Plugin used
强>
scoped_model: "^0.2.0"
<强> mainpage.dart
强>
import 'package:commo_drawer/drawer.dart';
import 'package:flutter/material.dart';
import 'view1.dart';
import 'view2.dart';
import 'view3.dart';
MainPageState mainPageState = new MainPageState();
class MainPage extends StatefulWidget {
@override
State<MainPage> createState() => mainPageState;
}
class MainPageState extends State<MainPage> {
MyDrawer myDrawer;
@override
void initState() {
myDrawer =
new MyDrawer(shouldRebuildState: DrawerItemClick.NEED_TO_REBUILD_STATE);
myDrawer.addListener(() {
setState(() {});
});
super.initState();
}
rebuild() {
setState(() {});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(drawerItems[myDrawer.selectedPageIndex].title),
),
drawer: myDrawer.buildDrawer(context),
body: _buildCurrentPage(),
);
}
Widget _buildCurrentPage() {
switch (myDrawer.selectedPageIndex) {
case 0:
return new View1();
case 1:
return new View2();
case 2:
return new View3();
}
return new Text('Invalid page index');
}
}
<强> subview1.dart
强>
import 'package:commo_drawer/drawer.dart';
import 'package:flutter/material.dart';
class SubView1 extends StatelessWidget {
final MyDrawer myDrawer = new MyDrawer(shouldRebuildState: DrawerItemClick.NEED_NOT_REBUILD_STATE);
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('SubView1'),
leading: new IconButton(
icon: new Icon(Icons.arrow_back),
onPressed: () {
Navigator.of(context).pop();
}),
),
body: new Text('Pushed from View1'),
drawer: myDrawer.buildDrawer(context),
);
}
}
<强> drawer.dart
强>
import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
int _selectedPageIndex = 0;
BuildContext _context;
class MyDrawer extends Model {
DrawerItemClick shouldRebuildState;
MyDrawer({this.shouldRebuildState});
int get selectedPageIndex => _selectedPageIndex;
Drawer buildDrawer(BuildContext context) {
_context = context;
return new Drawer(
child: new ListView(
padding: EdgeInsets.zero,
children: <Widget>[
new DrawerHeader(child: new Text('Drawer header')),
buildDrawerItem(0),
buildDrawerItem(1),
buildDrawerItem(2),
],
),
);
}
Widget buildDrawerItem(int index) {
return new ListTile(
title: new Text(drawerItems[index].title),
selected: selectedPageIndex == index,
onTap: () => _handleSelection(index),
);
}
void _handleSelection(int index) {
Navigator.of(_context).pop(); // Close drawer
if (shouldRebuildState == DrawerItemClick.NEED_TO_REBUILD_STATE) {
if (_selectedPageIndex != index) {
_selectedPageIndex = index;
notifyListeners();
}
} else {
shouldRebuildState = DrawerItemClick.NEED_TO_REBUILD_STATE;
Navigator.of(_context).pop(); // Close SubView
if (_selectedPageIndex != index) {
_selectedPageIndex = index;
notifyListeners();
}
}
}
}
final drawerItems = [
new DrawerItem(title: 'Item 1'),
new DrawerItem(title: 'Item 2'),
new DrawerItem(title: 'Item 3'),
];
class DrawerItem {
String title;
DrawerItem({this.title});
}
enum DrawerItemClick { NEED_TO_REBUILD_STATE, NEED_NOT_REBUILD_STATE }