flutter 主题更改时,抽屉关闭,如何防止这种情况发生?

uwopmtnx  于 2023-01-06  发布在  Flutter
关注(0)|答案(2)|浏览(115)

我在Scaffold抽屉里切换应用程序主题。每当我切换主题时,抽屉立即关闭。有没有办法在父级重建时保持抽屉窗体关闭?

return Drawer(
      child: ListView(
        // Important: Remove any padding from the ListView.
        padding: EdgeInsets.zero,
        children: <Widget>[
          const DrawerHeader(
            decoration: BoxDecoration(color: Color(0x4D4971FF)),
            //https://gist.github.com/lopspower/03fb1cc0ac9f32ef38f4
            child: Text(
              'Header',
              style: style,
            ),
          ),
          ListTile(
            leading: const Icon(Icons.brush),
            title: const Text(
              'Dark Mode',
              style: style,
            ),
            trailing: Switch(
              value: context.read<ThemeModeCubit>().state == ThemeMode.dark,
              onChanged: (value) {
                context.read<ThemeModeCubit>().toggleBrightness();
              },
            ),
          ),
       ]
      ),
   );

这是使用Cubit的构建器。StackOverflow说
看起来你的帖子大部分是代码;请补充一些细节。

class AppView extends StatelessWidget {
  const AppView({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<AuthenticationBloc, AuthenticationState>(
        builder: (context, authState) {
          final _router = AppRouter(
            status: authState.status,
            initialMessage: null,
          ).router;
          return MaterialApp.router(
            
            themeMode: context.watch<ThemeModeCubit>().state,
            debugShowCheckedModeBanner: false,
            routerConfig: _router,
          );
        },
     
    );
  }
}

这是腕尺

class ThemeModeCubit extends HydratedCubit<ThemeMode> {
  ThemeModeCubit() : super(ThemeMode.system);

  void toggleBrightness() {
    emit(state == ThemeMode.light ? ThemeMode.dark : ThemeMode.light);
  }

  @override
  ThemeMode? fromJson(Map<String, dynamic> json) {
    return ThemeMode.values[json['themeMode'] as int];
  }

  @override
  Map<String, dynamic>? toJson(ThemeMode state) {
    return <String, int>{'themeMode': state.index};
  }
}
    • 更新**
class AppView extends StatelessWidget {
  const AppView({super.key});

  @override
  Widget build(BuildContext context) {
    final _router = AppRouter(
      status: context.watch<AuthenticationBloc>().state.status,
      initialMessage: null,
    ).router;
    return MaterialApp.router(
        theme: AppTheme.of(context).light(),
        darkTheme: AppTheme.of(context).dark(),
        themeMode: context.watch<ThemeModeCubit>().state,
        debugShowCheckedModeBanner: false,
        routerConfig: _router,
      );
   
  
  }
}
ar7v8xwq

ar7v8xwq1#

您之所以面临这种情况,是因为BlocBuilder在每次state更改时都会构建,当您将状态更改为light时,状态也会更改,BlocBuilder下的整个Widget都会重建。

处理此问题的最佳方法是什么?

要使用BlocBuilderbuildWhen属性,请尝试在此处指定条件,并排除状态从亮变为暗或从暗变为亮的条件

代码结构:
BlocBuilder<BlocA, BlocAState>(
  buildWhen: (previous, current) {
    // return true/false to determine whether or not
    // to rebuild the widget with state
  },
  builder: (context, state) {
    // return widget here based on BlocA's state
  }
)
或者

将BlocBuilder作为一个整体移除,因为您只是更改状态以切换colorTheme。如果您没有使用buildWhen来防止抽屉重新呈现,则Drawer's范围应在BlocBuilder范围之外

建议

1.最重要的是,您的代码架构需要微调,因为引入BlocBuilder是为了在必要时仅构建所需的小部件。
1.强烈建议不要将整个MaterialApp封装在BlocBuilder中,并且根本不应该使用它,因为每一次状态更改,整个应用都在重建。
x一个一个一个一个x一个一个二个x
1.尝试使用MultiBlocProvider,而不是嵌套BlocProvider

pxiryf3j

pxiryf3j2#

通常情况下,这并不意味着这样做。作为Flutter只重新渲染连接到更改值的小部件。您确定您使用的BlocBuilder在正确的地方吗?
还要检查在BlocBuilder或Cubit的toggleBrightness方法中,您没有更新任何其他状态或值,而这些状态或值正在更新其他内容。
如果使用BlocListener并在其listen方法中设置一些值,如..,也会发生这种情况。

BlocListener<BlocA, BlocAState>(
  bloc: blocA,
  listener: (context, state) {
    // Check if you are updating some value inside this.
  }
)

您可以从这个url https://dartpad.dev/?id=c79010cc6c1f27b0c1846191603e4dc9测试我的示例代码,并检查您是否实现了这样的基本结构。
如果这不能解决你的问题,那么你可能要更新你的问题与更多的代码样本和细节。

在代码后更新

在这里,您在更改主题时更改了小部件,但在其中,另一个auth构建器正在创建一个新的路由器。

return BlocBuilder<ThemeModeCubit, ThemeMode>(
      builder: (context, themeMode) {
        return AppTheme(
          child: BlocBuilder<AuthenticationBloc, AuthenticationState>(
            builder: (context, authState) {
              final _router = AppRouter(
                status: authState.status,
                initialMessage: null,
              ).router;
              return MaterialApp.router(
                theme: AppTheme.of(context).light(),
                darkTheme: AppTheme.of(context).dark(),
                themeMode: themeMode,
                debugShowCheckedModeBanner: false,
                routerConfig: _router,
              );
            },
          ),
        );
      },
    );

试着像这样切换。

return BlocBuilder<AuthenticationBloc, AuthenticationState>(
      builder: (context, themeMode) {
        final _router = AppRouter(
        status: authState.status,
           initialMessage: null,
        ).router;
        return AppTheme(
          child: BlocBuilder<ThemeModeCubit, ThemeMode>(
            builder: (context, authState) {
              return MaterialApp.router(
                theme: AppTheme.of(context).light(),
                darkTheme: AppTheme.of(context).dark(),
                themeMode: themeMode,
                debugShowCheckedModeBanner: false,
                routerConfig: _router,
              );
            },
          ),
        );
      },
    );

相关问题