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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在BottomNavigationBar上更改选项卡时禁用重建页面相关的知识,希望对你有一定的参考价值。

我使用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'),     
        ],
      ),
      ),  
    );
  }
}

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

如果我改变屏幕,我想让我的屏幕保持活力。我怎样才能做到这一点?

答案

嗨,我已经实现了在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<>”,它将试图保持物体的存活。

希望这会有所帮助:)

以上是关于在BottomNavigationBar上更改选项卡时禁用重建页面的主要内容,如果未能解决你的问题,请参考以下文章

Flutter BottomNavigationBar 和高级导航

BottomNavigationBar 页面更改导致 StreamBuilder 数据重新加载

BottomNavigationBar-更改标签图标颜色

如何从名为 Next 的“bottomNavigationBar”按钮滑动到下一个选项卡?

每当更改 BottomNavigationBarItem 时,FutureBuilder 都会重新加载

Flutter -------- BottomNavigationBar 界面切换