navigation - 如何 - 带有持久子屏幕的 Flutter Drawer

标签 navigation flutter drawer

我是 Flutter 的新手,我正在尝试找出如何实现我在网络编程方面所做的事情,即拥有一个具有多个“区域”的应用程序,这些“区域”可以同时处于“实时/当前”状态.想象一个应用程序有 4 个“区域”。 4 个区域中的每一个都有一个“开始”屏幕,通常是该区域中的项目列表。用户可以使用该区域的辅助“子”屏幕查看列表项的详细信息,或创建新的列表项。 4 个“区域”屏幕中的每一个还包括一个抽屉,用于将“当前 View ”切换到特定区域。这个概念是:用户可以转到一个区域、滚动列表、过滤列表等。然后他们可以要求抽屉转到另一个区域,在那里他们可以在该屏幕上执行类似的操作。然后他们应该能够使用抽屉 [重新] 转到第一个区域,或转到他们想要的任何其他区域,并且当他们到达那里时,该屏幕的“内容”(数据)应该与它完全相同在他们离开那个屏幕之前。请注意,如果他们“深入”列表项或创建新项,则他们无法访问“区域抽屉”,只能“返回”到该区域的列表屏幕。

在网络编程中,每个“区域”都是一个 div,并且都“存在”在一个页面上。抽屉元素会根据用户的需要简单地隐藏和显示每个 div,并且每个 div 在隐藏时都保持“不变”。

所以,问题是:如何在 Flutter 中实现这样的功能?我正在慢慢理解“小部件树”的事情,但是,随着“屏幕”(实际上只是小部件)被“推”到树中,当前显示的屏幕会发生什么情况?我了解导航堆栈,但是前一个屏幕、它的小部件和它的数据(内存)会发生什么?它们会从树上“消失”吗?从我之前看到的问题来看,我认为答案是"is"。一旦“推离”屏幕被“重新插入”,它就会重新开始它的生活,这意味着它必须重新获取数据、滚动它、过滤它、渲染它等等。

我想我想知道的是,该应用程序能否同时在内存中、树中有多个“区域”(屏幕),但一次只能“看到”一个,并且每个区域都有自己的自己的“ child 屏幕导航”。我确信我正在以“错误”的方式处理问题,但每个工具包/编程系统似乎都以不同的方式处理这个问题,我只是不确定如何使用 Flutter 来解决这个问题。我知道我可以将每个区域的“开始”页面的所有“数据”保留在内存中(在应用程序级别),因此可以从该数据重建每个区域(无需转到数据库)。我还听过一些人讨论“线性导航”(相对于分层导航?),但对此知之甚少。

感谢您的帮助。

最佳答案

这与我们几个月前遇到的问题非常相似。我们有一个抽屉,上面有四个不同 list 的链接。这些列表彼此完全独立,并且是它们自己的页面。您还可以点击列表中的其中一项,然后进入详细信息页面。

(一旦您进入详细信息页面,您只能点击后退按钮,抽屉仅在列表和其他顶级页面上可用)。

列表本身是可排序、分页、过滤和快速搜索的。每个列表将其状态保存到基于继承的小部件模式的 session 中。我的 Session 类基于这篇文章:

Flutter: How to correctly use an Inherited Widget?

如果您转到列表 A,对一列进行排序,使用抽屉移动到列表 B,然后按回键返回列表 A,该列表将显示为您离开时的状态。

如果您要转到列表 A,对一列进行排序,使用抽屉移动到列表 B,然后再次使用抽屉转到列表 A,列表将显示为您离开时的相同状态。

这两种情况的区别在于导航堆栈的外观。在第一种情况下,堆栈只是列表 A。在第二种情况下,堆栈是列表 A、列表 B、列表 A。

如果您采用第二种情况,对列表 A 进行更改,然后弹出堆栈两次(点击后退按钮),堆栈底部的列表 A 实际上看起来就像您更改的更高层的列表 A在堆栈上。

下面是支持保存其中一个列表状态的 Session 类的部分 View 。请注意,这是有意称为 Session 的,当应用程序关闭时,应用程序会忘记此状态。不过,保存到共享存储会相对容易。

class Session extends StatefulWidget {
  final Widget child;

  Session({this.child});

  @override
  SessionState createState() => SessionState();

  static SessionState of(BuildContext context) {
    return (context.inheritFromWidgetOfExactType(_Session) as _Session).data;
  }
}

class SessionState extends State<Session> {
  ListPagePreferences _myListPrefs = ListPagePreferences();

  //called when the user logs out, for example
  void clear() {
    setState(() {
      _myListPrefs = ListPagePreferences();
    });
  }

  ListPagePreferences get myListPrefs => _myListPrefs;

  void updatePrefs({
    ListPagePreferences prefs,
    rowsPerPage,
    startIndex,
    sortColumnIndex,
    sortAscending,
    searchValue,
    filter,
  }) {
    setState(() {
      prefs.updatePrefs(
        rowsPerPage: rowsPerPage,
        startIndex: startIndex,
        sortColumnIndex: sortColumnIndex,
        sortAscending: sortAscending,
        searchValue: searchValue,
        filter: filter,
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return _Session(
      data: this,
      child: widget.child,
    );
  }
}

class _Session extends InheritedWidget {
  final SessionState data;

  _Session({Key key, this.data, Widget child}) : super(key: key, child: child);

  @override
  bool updateShouldNotify(_Session old) => true;
}

然后我的应用程序被这个继承的小部件包裹:

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() {
    return _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return Session(
      child: MaterialApp(
        title: "My App",
        home: WelcomePage(),
      ),
    );
  }
}

这意味着我可以从应用程序的任何位置访问 session 并将内容存储在其中。它在应用程序中任何地方的使用方式如下:

ListPagePreferences savedPrefs = Session.of(context).myListPrefs;

还有其他方法可以保存状态,但这对我们的需求来说非常简单易行。

关于navigation - 如何 - 带有持久子屏幕的 Flutter Drawer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52959801/

相关文章:

ios - 如何在 Flutter 中禁用 InAppWebView 的缩放?

flutter - 不要将 Dart 视为 Android Studio 4.2.1 版中的语言

AppBar 下方的 Flutter Drawer

android - 不同 Activity 中的相同抽屉导航

dart - Widget示例和Widget * get *示例有什么区别?

react-native - 如何设置 react-native-navigation drawer 的主要父级宽度

css - 转到子链接时 Laravel CSS 不起作用

html - 我的图像链接后面显示红色 block

javascript - jquery - 关闭后显示元素

jquery - 填充 jQuery 下拉菜单项