在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:
下面是包含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 数据重新加载
如何从名为 Next 的“bottomNavigationBar”按钮滑动到下一个选项卡?