首页 文章

当使用BottomNavigationBar导航时,如何在颤动中保留窗口小部件状态?

提问于
浏览 1017
5

我正在制作一个Flutter应用程序,它将在从一个屏幕导航到另一个屏幕时保留状态,并在使用BottomNavigationBar时再次返回 . 就像它在Spotify移动应用程序中工作一样;如果您在其中一个主屏幕上导航层次结构中导航到某个级别,通过底部导航栏更改屏幕,然后更改回旧屏幕,将保留用户在该层次结构中的位置,包括保留国家 .

我把头靠在墙上,尝试各种不同的事情而没有成功 .

我想知道如何阻止 pageChooser() 中的页面,当用户点击BottomNavigationBar项目时切换,重建自己,而是保留他们已经找到的状态(页面都是有状态的Widgets) .

import 'package:flutter/material.dart';
import './page_plan.dart';
import './page_profile.dart';
import './page_startup_namer.dart';

void main() => runApp(new Recipher());

class Recipher extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Pages();
  }
}

class Pages extends StatefulWidget {
  @override
  createState() => new PagesState();
}

class PagesState extends State<Pages> {
  int pageIndex = 0;


  pageChooser() {
    switch (this.pageIndex) {
      case 0:
        return new ProfilePage();
        break;

      case 1:
        return new PlanPage();
        break;

      case 2:
        return new StartUpNamerPage(); 
        break;  

      default:
        return new Container(
          child: new Center(
            child: new Text(
              'No page found by page chooser.',
              style: new TextStyle(fontSize: 30.0)
              )
            ),
          );     
    }
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        body: pageChooser(),
        bottomNavigationBar: new BottomNavigationBar(
          currentIndex: pageIndex,
          onTap: (int tappedIndex) { //Toggle pageChooser and rebuild state with the index that was tapped in bottom navbar
            setState(
              (){ this.pageIndex = tappedIndex; }
              ); 
            },
          items: <BottomNavigationBarItem>[
            new BottomNavigationBarItem(
              title: new Text('Profile'),
              icon: new Icon(Icons.account_box)
              ),
              new BottomNavigationBarItem(
                title: new Text('Plan'),
                icon: new Icon(Icons.calendar_today)
              ),
                new BottomNavigationBarItem(
                title: new Text('Startup'),
                icon: new Icon(Icons.alarm_on)
              )
            ],
          )
      )
    );
  }
}

2 回答

  • 1

    使用AutomaticKeepAliveClientMixin强制不处理您的标签内容 .

    class PersistantTab extends StatefulWidget {
      @override
      _PersistantTabState createState() => _PersistantTabState();
    }
    
    class _PersistantTabState extends State<PersistantTab> with AutomaticKeepAliveClientMixin {
      @override
      Widget build(BuildContext context) {
        return Container();
      }
    
      // Setting to true will force the tab to never be disposed. This could be dangerous.
      @override
      bool get wantKeepAlive => true;
    }
    

    要确保标签在不需要保留时处理,请使 wantKeepAlive 返回一个类变量 . 您必须调用 updateKeepAlive() 来更新保持活动状态 .

    动态保持活动的示例:

    // class PersistantTab extends StatefulWidget ...
    
    class _PersistantTabState extends State<PersistantTab>
        with AutomaticKeepAliveClientMixin {
      bool keepAlive = false;
    
      @override
      void initState() {
        doAsyncStuff();
      }
    
      Future doAsyncStuff() async {
        keepAlive = true;
        updateKeepAlive();
        // Keeping alive...
    
        await Future.delayed(Duration(seconds: 10));
    
        keepAlive = false;
        updateKeepAlive();
        // Can be disposed whenever now.
      }
    
      @override
      bool get wantKeepAlive => keepAlive;
    
      @override
      Widget build(BuildContext context) {
        return Container();
      }
    }
    
  • 0

    每次运行 pageChooser 时,不是返回新实例,而是创建一个实例并返回相同的实例 .

    例:

    class Pages extends StatefulWidget {
      @override
      createState() => new PagesState();
    }
    
    class PagesState extends State<Pages> {
      int pageIndex = 0;
    
      // Create all the pages once and return same instance when required
      final ProfilePage _profilePage = new ProfilePage(); 
      final PlanPage _planPage = new PlanPage();
      final StartUpNamerPage _startUpNamerPage = new StartUpNamerPage();
    
    
      Widget pageChooser() {
        switch (this.pageIndex) {
          case 0:
            return _profilePage;
            break;
    
          case 1:
            return _planPage;
            break;
    
          case 2:
            return _startUpNamerPage;
            break;
    
          default:
            return new Container(
              child: new Center(
                  child: new Text(
                      'No page found by page chooser.',
                      style: new TextStyle(fontSize: 30.0)
                  )
              ),
            );
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
            home: new Scaffold(
                body: pageChooser(),
                bottomNavigationBar: new BottomNavigationBar(
                  currentIndex: pageIndex,
                  onTap: (int tappedIndex) { //Toggle pageChooser and rebuild state with the index that was tapped in bottom navbar
                    setState(
                            (){ this.pageIndex = tappedIndex; }
                    );
                  },
                  items: <BottomNavigationBarItem>[
                    new BottomNavigationBarItem(
                        title: new Text('Profile'),
                        icon: new Icon(Icons.account_box)
                    ),
                    new BottomNavigationBarItem(
                        title: new Text('Plan'),
                        icon: new Icon(Icons.calendar_today)
                    ),
                    new BottomNavigationBarItem(
                        title: new Text('Startup'),
                        icon: new Icon(Icons.alarm_on)
                    )
                  ],
                )
            )
        );
      }
    }
    

    或者您可以使用像PageViewStack这样的小部件来实现相同的功能 .

    希望有所帮助!

相关问题