I have a login screen. When logo is clicked, I want display a loading on top of it. The loading widget I put in ContainerWithLoadingOverlay
.
main.dart
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider(create: (_) => sl<OverlayLoadingCubit>()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
localizationsDelegates: [
EasyLocalization.of(context)!.delegate,
],
supportedLocales: EasyLocalization.of(context)!.supportedLocales,
locale: EasyLocalization.of(context)!.locale,
title: kAppTitle,
theme: AppTheme.light,
onGenerateRoute: AppRoute.onGenerateRoutes,
),
);
}
}
log_in_screen.dart
return Scaffold(
body: ContainerWithLoadingOverlay( <--- this for loading
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(32.0),
child: Center(
child: Column(
children: [
const AppLogo(
width: 150,
height: 150,
),
const SizedBox(height: 32),
InkWell(
onTap: () {
context.read<LogInCubit>().signIn(
SignInParams(
email: _emailController.text,
password: _passwordController.text));
},
child: Text(
"Welcome back.",
style: Theme.of(context).textTheme.headline4,
)),
const SizedBox(height: 32),
// _loginForm(context, isShown),
],
),
))),
));
}
log_in_cubit.dart
class LogInCubit extends Cubit<LogInState> {
final OverlayLoadingCubit _loadingCubit;
final SignInUseCase _useCase;
LogInCubit(this._useCase, this._loadingCubit) : super(LogInLoading());
Future<void> signIn(SignInParams params) async {
_loadingCubit.startLoading();
...
}
}
overlay_loading_state.dart
part of 'overlay_loading_cubit.dart';
abstract class OverlayLoadingState {
const OverlayLoadingState();
}
class OverlayLoadingInitial extends OverlayLoadingState {}
class IsLoadingState extends OverlayLoadingState {}
overlay_loading_cubit.dart
class OverlayLoadingCubit extends Cubit<OverlayLoadingState> {
OverlayLoadingCubit() : super(OverlayLoadingInitial());
startLoading() {
debugPrint("start loading"); <-- this line is able to print
emit(IsLoadingState());
return;
}
}
container_with_loading_overlay.dart
class ContainerWithLoadingOverlay extends HookWidget {
final Widget child;
const ContainerWithLoadingOverlay({Key? key, required this.child})
: super(key: key);
@override
Widget build(BuildContext context) {
return BlocListener<OverlayLoadingCubit, OverlayLoadingState>(
listener: (context, state) {
debugPrint("call from listener"); <--- this line not calling
if (state is OverlayLoadingInitial) {
context.loaderOverlay.hide();
}
if (state is IsLoadingState) {
context.loaderOverlay.show();
}
},
child: LoaderOverlay(
useDefaultLoading: false,
overlayWidget: const Center(child: CircularProgressIndicator()),
child: child,
),
);
}
}
I expect the bloc listener in class ContainerWithLoadingOverlay
will get triggered and loading dialog will show, but it not triggred..what's the issue?
The BlocListener is triggered only when it detects a state change. If your BlocListener is not being triggered, try emitting an OverlayLoadingInitial() state first, wait for a second, and then emit the isLoadingStates state.
Here's an example code:
void startLoading() {
// debugPrint("start loading"); <-- this line is able to print
emit(OverlayLoadingInitial());
await Future.delayed(const Duration(seconds: 1)); // Emulates your signIn request
emit(IsLoadingState());
return;
}