颤动:使用导航器

时间:2018-05-30 07:45:05

标签: flutter

链接到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课程,但我更喜欢材料设计。有人能指出我如何实现所需行为的正确方向吗?

1 个答案:

答案 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 }