在构建 CupertinoTabScaffold 期间调用 setState() 或 markNeedsBuild()
Posted
技术标签:
【中文标题】在构建 CupertinoTabScaffold 期间调用 setState() 或 markNeedsBuild()【英文标题】:setState() or markNeedsBuild() called during build CupertinoTabScaffold 【发布时间】:2021-06-06 23:22:59 【问题描述】:我有使用 CupertinoTabScaffold 显示底部导航的代码,我想在其中一个菜单上显示底部对话框,但出现错误
在构建 Builder 时抛出了以下断言(脏,依赖项:[_InheritedTheme,_LocalizationsScope-[GlobalKey #a6d51]]): 构建期间调用的 setState() 或 markNeedsBuild()。
这是我的代码
class AppTab extends StatefulWidget
final dataUser;
AppTab(this.dataUser);
@override
_AppTabState createState() => _AppTabState(dataUser);
class _AppTabState extends State<AppTab>
final user;
_AppTabState(this.user);
@override
Widget build(BuildContext context)
return BlocListener<AuthenticationBloc, AuthenticationState>(
listener: (context, state)
if (state == AuthenticationState.unauthenticated())
Navigator.pushNamedAndRemoveUntil(context, '/login', (route) => false, arguments: state.loginPageState);
,
child: CupertinoTabScaffold(
controller: tabController,
tabBar: CupertinoTabBar(
activeColor: HexColor("#26ADE4"),
inactiveColor: HexColor("#707070"),
items: [
BottomNavigationBarItem(
label: "Menu 1",
icon: Image.asset("assets/icon_tab_home.png", height: 25, width: 22),
activeIcon: Image.asset("assets/icon_tab_home_active.png", height: 25, width: 22),
),
BottomNavigationBarItem(
label: "Menu 2",
icon: Image.asset("assets/icon_tab_buat_bill.png", height: 25, width: 22),
activeIcon: Image.asset("assets/icon_tab_buat_bill_active.png", height: 25, width: 22),
),
BottomNavigationBarItem(
label: "Menu 3",
icon: Image.asset("assets/icon_tab_account.png", height: 25, width: 22),
activeIcon: Image.asset("assets/icon_tab_account_active.png", height: 25, width: 22),
),
],
),
tabBuilder: (context, index)
if (index == 0)
return HomePage(user);
else if (index == 1)
return _bottomSheetMore(context);
return AccountPage(user);
),
);
_bottomSheetMore(context)
showModalBottomSheet(
context: context,
builder: (builder)
return new Container(
padding: EdgeInsets.only(
left: 5.0,
right: 5.0,
top: 5.0,
bottom: 5.0,
),
decoration: new BoxDecoration(
color: Colors.white,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(10.0),
topRight: const Radius.circular(10.0))),
child: new Wrap(
children: <Widget>[
new ListTile(
title: const Text(
'Menu Akun',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w700,
),
),
subtitle: Text("Pilih salah satu"),
),
new Divider(
height: 10.0,
),
new ListTile(
title: const Text(
'Menu Home',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w700,
),
),
),
new Divider(
height: 10.0,
),
new ListTile(
title: const Text(
'Logout',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w700,
),
),
onTap: () async
// Add Here
,
),
],
),
);
,
);
【问题讨论】:
【参考方案1】:它会显示该错误,因为在显示模态底部表单之前应该先绘制小部件。要显示模态底部表,请在 Future.delayed(...)
中调用它。
你可以试试这样的。
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: AppTab()));
class AppTab extends StatefulWidget
@override
_AppTabState createState() => _AppTabState();
class _AppTabState extends State<AppTab>
final CupertinoTabController _controller = CupertinoTabController();
final List<CupertinoPageScaffold> _pages = <CupertinoPageScaffold>[
CupertinoPageScaffold(
child: const Center(child: Text('Home Page')),
),
CupertinoPageScaffold(
child: const Center(child: Text('2nd Page')),
),
CupertinoPageScaffold(
child: const Center(child: Text('Account Page')),
),
];
bool _isBottomSheetShown = false;
@override
Widget build(BuildContext context)
return Scaffold(
body: CupertinoTabScaffold(
controller: _controller,
tabBar: CupertinoTabBar(
activeColor: Colors.red,
inactiveColor: Colors.blue,
items: const [
BottomNavigationBarItem(
label: "Menu 1",
icon: Icon(Icons.ac_unit),
),
BottomNavigationBarItem(
label: "Menu 2",
icon: Icon(Icons.local_activity),
),
BottomNavigationBarItem(
label: "Menu 3",
icon: Icon(Icons.assessment),
),
],
),
tabBuilder: (context, index)
return CupertinoTabView(
builder: (BuildContext context)
if (_controller.index == 1 && index == 1)
_bottomSheetMore(context);
return _pages[index];
,
);
,
),
);
Future<void> _bottomSheetMore(context) async
if (_isBottomSheetShown)
return;
_isBottomSheetShown = true;
await Future<void>.delayed(
const Duration(milliseconds: 10),
() => showModalBottomSheet<void>(
context: context,
builder: (_)
return Container(
height: 300,
padding: const EdgeInsets.all(5),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(10.0),
topRight: const Radius.circular(10.0),
),
),
child: Wrap(
children: <Widget>[
ListTile(
title: const Text(
'Menu Akun',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w700,
),
),
subtitle: const Text("Pilih salah satu"),
),
const Divider(height: 10.0),
ListTile(
title: const Text(
'Menu Home',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w700,
),
),
),
const Divider(height: 10.0),
ListTile(
title: const Text(
'Logout',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w700,
),
),
onTap: () async
// Add Here
,
),
],
),
);
,
),
);
_isBottomSheetShown = false;
@override
void dispose()
super.dispose();
_controller.dispose();
【讨论】:
以上是关于在构建 CupertinoTabScaffold 期间调用 setState() 或 markNeedsBuild()的主要内容,如果未能解决你的问题,请参考以下文章
Flutter——WidgetBottomNavigationBar与CupertinoTabScaffold