setState() 或 markNeedsBuild() 在构建期间调用 CupertinoTabScaffold

时间:2021-03-09 04:05:03

标签: flutter dialog setstate

我有使用 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 个答案:

答案 0 :(得分: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();
  }
}