在BottomNavigationBar上的选项卡更改时禁用重建页面

时间:2019-04-21 08:57:48

标签: dart flutter

我使用bmnav来实现底部导航栏。 这是我的实现。

main.dart

class MainWidgetState extends State<MainWidget> {

   @override
  void initState(){
    super.initState();
  }
  int currentTab = 0;

  final List<Widget> screens = [
    MapSample(), Workouts(), Account()
  ];
  Widget currentScreen = MapSample();

  final PageStorageBucket bucket = PageStorageBucket();

  @override
  Widget build(BuildContext ctx) {
    return Scaffold(     
      body: PageStorage(child: currentScreen, bucket: bucket),
      bottomNavigationBar: SizedBox(height: 45,  
        child: bmnav.BottomNav(
        index: currentTab,
        onTap: (i) {
          setState(() {
            currentTab = i;
            currentScreen = screens[i];
          });
        },
        labelStyle: bmnav.LabelStyle(visible: true,  
        items: [
          bmnav.BottomNavItem(OMIcons.map, label: 'Map'),
          bmnav.BottomNavItem(OMIcons.cast, label: 'Workouts'),
          bmnav.BottomNavItem(OMIcons.textsms, label: 'Account'),     
        ],
      ),
      ),  
    );
  }
}

当我从索引屏幕切换到其他屏幕并返回索引屏幕时,索引屏幕将始终重建。

如果要更换屏幕,我希望屏幕保持活动状态。我该怎么办?

1 个答案:

答案 0 :(得分:1)

嗨,我已经实现了在BottomNavigationBar的选项卡更改时禁用重建页面的功能。

我还在下面附加了gif:

enter image description here

下面是带有3个选项卡的完整示例,该示例具有其自己的变量,可以使用保留值进行更新,并在更改选项卡时保持活动状态:

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_demo_app/list.dart';
import 'package:bmnav/bmnav.dart' as bmnav;

MyHomeMapSample valMapSample = null;
MyHomeWorkouts valWorkouts = null;
MyHomeAccount valAccount = null;

MapSample mapSample = null;
Workouts workouts = null;
Account account = null;

Widget currentScreen = null;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    ButtonsLists.context = context;
    currentScreen = MyHomeMapSample();
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

}



class _MyHomePageState extends State<MyHomePage> {

  @override
  void initState(){
    super.initState();
    debugPrint("currentTab: _MyHomePageState super.initState();");
  }
  int currentTab = 0;

  final PageStorageBucket bucket = PageStorageBucket();

  @override
  Widget build(BuildContext ctx) {
    debugPrint('currentTab: $currentTab');
    return Scaffold(

      body: PageStorage(child: currentScreen, bucket: bucket),
      bottomNavigationBar: SizedBox(height: 58,
        child: bmnav.BottomNav(
          index: currentTab,
          onTap: (i) {
            setState(() {
              currentTab = i;
              currentScreen = getWidget(context, i);
              debugPrint('inner currentTab: $currentTab');
              debugPrint('inner currentScreen: $currentScreen');
            });
          },
          labelStyle: bmnav.LabelStyle(visible: true),
          items: [
            bmnav.BottomNavItem(Icons.map, label: 'Map'),
            bmnav.BottomNavItem(Icons.cast, label: 'Workouts'),
            bmnav.BottomNavItem(Icons.textsms, label: 'Account'),
          ],
        ),
      ),
      resizeToAvoidBottomPadding: true,
    );
  }

  Widget getWidget(BuildContext context, int i){
    if(i==0){
      if(valMapSample == null){
        valMapSample = MyHomeMapSample();
        mapSample = valMapSample.createState();
        return valMapSample;
      }else{
        return mapSample.build(context);
      }
    }

    else if(i==1){
      if(valWorkouts == null){
        valWorkouts = MyHomeWorkouts();
        workouts = valWorkouts.createState();
        return valWorkouts;
      }else{
        return workouts.build(context);
      }

    }else if(i==2){
      if(valAccount == null){
        valAccount = MyHomeAccount();
        account = valAccount.createState();
        return valAccount;
      }else{
        return account.build(context);
      }
    }
  }

}



class MyHomeMapSample extends StatefulWidget {
  MyHomeMapSample({Key key}) : super(key: key);
  @override
  MapSample createState() => MapSample();
}

class MapSample extends State<MyHomeMapSample> with AutomaticKeepAliveClientMixin {
  var myVariable = 0;

  @override
  void initState(){
    super.initState();
    debugPrint('current: MapSample: initState() called!');
  }

  @override
  Widget build(BuildContext context) {
    myVariable = myVariable + 1;
    return Scaffold(
      appBar: AppBar(
        title: Text('MapSample'),
      ),
      body: Center(
        child: Text('MapSample details + $myVariable'),
      ),
      resizeToAvoidBottomPadding: true,
    );
  }

  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;

}



class MyHomeWorkouts extends StatefulWidget {
  MyHomeWorkouts({Key key}) : super(key: key);
  @override
  Workouts createState() => Workouts();
}

class Workouts extends State<MyHomeWorkouts> with AutomaticKeepAliveClientMixin {
  var myVariable = 0;

  @override
  void initState(){
    super.initState();
    debugPrint('current: Workouts: initState() called!');
  }

  @override
  Widget build(BuildContext context) {
    myVariable = myVariable + 1;
    return Scaffold(
      appBar: AppBar(
        title: Text('Workouts'),
      ),
      body: Center(
        child: Text('Workouts details + $myVariable'),
      ),
      resizeToAvoidBottomPadding: true,
    );
  }

  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;

}




class MyHomeAccount extends StatefulWidget {
  MyHomeAccount({Key key}) : super(key: key);
  @override
  Account createState() => Account();
}

class Account extends State<MyHomeAccount> with AutomaticKeepAliveClientMixin {
  var myVariable = 0;

  @override
  void initState(){
    super.initState();
    debugPrint('current: Account: initState() called!');
  }

  @override
  Widget build(BuildContext context) {
    myVariable = myVariable + 1;
    return Scaffold(
      appBar: AppBar(
        title: Text('Account'),
      ),
      body: Center(
        child: Text('Account details + $myVariable'),
      ),
      resizeToAvoidBottomPadding: true,
    );
  }

  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;

}

我所做的是在全局创建“ StatefulWidget”和“ State<>”类对象,然后借助“ createState()”的“ StatefulWidget”方法和“ .build(context)”类的“ State<>”方法, 我已阻止调用“ initState()”方法并更新没有它的小部件。 我也用“ with AutomaticKeepAliveClientMixin”来表示“ State<>”,这将试图使对象保持活动状态。

希望这会有所帮助:)