保留选项卡视图页面之间的状态

时间:2018-03-03 18:29:26

标签: dart flutter

问题

我使用ListViewsTabBarView内进行了两次TabController渲染。

如何在每个ListView之间保留状态(缺少更好的词),以便:1)小部件不重建,以及2.)在标签之间记住ListView位置

相关代码

class AppState extends State<App> with SingleTickerProviderStateMixin {
  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = new TabController(
      vsync: this,
      length: _allPages.length,
    );
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  Widget _buildScaffold(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('headlines'),
        bottom: new TabBar(
            controller: _tabController,
            isScrollable: true,
            tabs: _allPages
                .map((_Page page) => new Tab(text: page.country))
                .toList()),
      ),
      body: new TabBarView(
          controller: _tabController,
          children: _allPages.map((_Page page) {
            return new SafeArea(
              top: false,
              bottom: false,
              child: new Container(
                key: new ObjectKey(page.country),
                child: new Newsfeed(country: page.country),
              ),
            );
          }).toList()),
    );
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'news app',
      home: _buildScaffold(context),
    );
  }
}

说明了gif

https://media.giphy.com/media/2ysWhzqHVqL1xcBlBE/giphy.gif

5 个答案:

答案 0 :(得分:16)

如果要将屏幕状态保留在TabBarView中,可以在State类中使用名为AutomaticKeepAliveClientMixin的mixin类。

此后,您必须覆盖wantKeepAlive方法并返回true

我在这里写了一篇关于此的帖子:https://medium.com/@diegoveloper/flutter-persistent-tab-bars-a26220d322bc

答案 1 :(得分:6)

长话短说,请为您的ListView或其中一个祖先使用PageStorageKey(),在您的情况下使用Container小部件:

child: new Container(
    key: new PageStorageKey(page.country),
    child: new Newsfeed(country: page.country),
),

详情请见:

答案 2 :(得分:6)

在我们的国家使用mixinAutomaticKeepAliveClientMixin

并实施:bool get wantKeepAlive => true;

class ResidentListScreen extends StatefulWidget {
  @override
  _ResidentListScreenState createState() => _ResidentListScreenState();
}

class _ResidentListScreenState extends State<ResidentListScreen> with 
AutomaticKeepAliveClientMixin<ResidentListScreen>{

  @override
  bool get wantKeepAlive => true;

  @override
  void initState() {
   super.initState();
  }

 @override
 Widget build(BuildContext context) { 

 }
}

答案 3 :(得分:0)

尝试在带有偏移量的堆栈中包含子视图。它帮助我保存了我的底栏导航状态。

答案 4 :(得分:0)

我遵循了这些建议,但是这些建议没有用,所以我创建了自己的建议。到目前为止,效果很好。

我的解决方案。
基本上只是一个水平ListView,其中禁用了滚动并且元素上的最大宽度。我正在使用一个非常繁重的标签(Google地图)对其进行测试,并且效果很好。

包含上述元素的列表视图:

  Widget body(BuildContext context) {
    final double width = MediaQuery.of(context).size.width;

    return ListView(
      controller: scrollController,
      scrollDirection: Axis.horizontal,
      physics: NeverScrollableScrollPhysics(),
      children: <Widget>[
        Container(width: width, child: TabLiveEvents()),
        Container(width: width, child: TabEvents()),
      ],
    );
  }

标签栏布局。

  Widget bottomNavbar(BuildContext context) {
    return BottomNavigationBar(
      items: [
        BottomNavigationBarItem(
            icon: Icon(Icons.chat_bubble),
            title: Text(Translation.tabMeetupText)),
        BottomNavigationBarItem(
            icon: Icon(Icons.list), title: Text(Translation.tabEventslist)),
      ],
      currentIndex: _selectedIndex,
      fixedColor: Theme.of(context).accentColor,
      onTap: _onItemTapped,
    );
  }

通过点击项目切换列表视图时。

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });

    double width = MediaQuery.of(context).size.width * index;
    scrollController.jumpTo(width);
  }

主窗口小部件

@override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: appBar(),
        bottomNavigationBar: bottomNavbar(context),
        body: body(context),
      ),
    );
  }