How To - 带有持久子屏幕的 Flutter Drawer
Posted
技术标签:
【中文标题】How To - 带有持久子屏幕的 Flutter Drawer【英文标题】:How To - Flutter Drawer with persistent child screens 【发布时间】:2019-03-28 07:49:53 【问题描述】:我是 Flutter 的新手,正在尝试找出如何实现我在 Web 编程方面所做的事情,即拥有一个具有多个“区域”的应用程序,这些“区域”都可以同时处于“实时/当前”状态.想象一个有 4 个“区域”的应用程序。 4 个区域中的每一个都有一个“开始”屏幕,通常是该区域内的项目列表。用户可以使用该区域的辅助“子”屏幕查看列表项的详细信息,或创建新的列表项。 4 个“区域”屏幕中的每一个还包括一个抽屉,用于将“当前视图”切换到特定区域。这个概念是:用户可以去一个区域,滚动列表,过滤列表等。然后他们可以要求抽屉去一个不同的区域,在那里他们可以在那个屏幕上执行类似的操作。然后他们应该能够使用抽屉 [re] 去第一个区域,或者去他们想要的任何其他区域,并且,当他们到达那里时,该屏幕的“内容”(数据)应该与它完全相同在他们离开那个屏幕之前。请注意,如果他们“深入”列表项或创建新项,他们将无法访问“区域抽屉”,只能“返回”到该区域的列表屏幕。
在网络编程中,每个“区域”都是一个 div,并且都“存在”在一个页面上。抽屉元素会根据用户的需要简单地隐藏和显示每个 div,每个 div 在隐藏时都保持“未触及”。
所以,问题是:如何在 Flutter 中实现这样的功能?我正在慢慢理解“小部件树”的事情,但是,当“屏幕”(实际上只是小部件)被“推”到树中时,当前显示的屏幕会发生什么?我了解导航堆栈,但是前一个屏幕、它的小部件和它的数据(内存)会发生什么?他们会从树上“抹去”吗?从我以前看到的问题来看,我认为答案是“是”。一旦“被推开”的屏幕被“重新推”到,它就会重新开始它的生命,这意味着它必须重新获取数据、滚动、过滤、渲染等等。
我想我想知道的是,该应用程序是否可以同时在内存中、树中具有多个“区域”(屏幕),但一次只能“看到”一个,并且每个区域都有其自己的“子屏幕导航”。我确信我以“错误”的方式处理事情,但每个工具包/编程系统似乎都以不同的方式处理这个问题,我只是不确定如何使用 Flutter 来解决这个问题。我知道我可以将每个区域的“开始”页面的所有“数据”保存在内存中(在应用程序级别),因此可以从该数据重新构建每个区域(无需进入数据库)。我还听一些人讨论过“线性导航”(相对于分层?),但对此知之甚少。
感谢您的帮助。
【问题讨论】:
【参考方案1】:这与我们几个月前遇到的问题非常相似。我们有一个抽屉,里面有四个不同列表的链接。这些列表彼此完全独立,并且是它们自己的页面。您还可以点击列表中的其中一项并进入详细信息页面。
(一旦您进入详细信息页面,您只能点击返回按钮,抽屉仅在列表和其他***页面上可用)。
列表本身是可排序的、分页的、可以过滤的和快速搜索的。每个列表都将其状态保存到基于 Inherited Widget 模式的会话中。我的 Session 课程基于这篇文章:
Flutter: How to correctly use an Inherited Widget?
如果您要转到列表 A,对列进行排序,使用抽屉移动到列表 B,然后回击返回列表 A,则列表将显示为与您离开时相同的状态。
如果您要转到列表 A,对列进行排序,使用抽屉移动到列表 B,然后再次使用抽屉转到列表 A,列表将显示为与您离开时相同的状态。
这两种情况之间的区别在于导航堆栈的外观。在第一种情况下,堆栈只是列表 A。在第二种情况下,堆栈是列表 A、列表 B、列表 A。
如果您要采用第二种情况,对 List A 进行更改,然后将堆栈弹出两次(按返回按钮),堆栈底部的 List A 实际上看起来像您在更高位置更改的 List A在堆栈上。
下面是我的 Session 类的部分内容,它支持保存其中一个列表的状态。请注意,这被故意称为 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;
还有其他方法可以保存状态,但这对于我们的需要来说非常简单明了。
【讨论】:
以上是关于How To - 带有持久子屏幕的 Flutter Drawer的主要内容,如果未能解决你的问题,请参考以下文章
Flutter How to Scaffold layout size(错误)
Flutter: How to fix ITMS-90809: Deprecated API Usage - Apple 将停止接受使用 UIWebView API 的应用程序提交