Repository: flutter
Issue: I have flicker with Flutter App On Android and sometimes on iOS
Labels: waiting for customer response,in triage

### Steps to reproduce

1. I have a page on scroll or speed movement i have flicker

### Expected results

The scroll does not working correctly 

### Actual results

I have flicker


### Code sample

<details open><summary>Code sample</summary>

```dart
import 'package:austro_digital/app/login/_children/register_austrotoken_login/presenter/blocs/camera_access_bloc/camera_access_bloc.dart';
import 'package:austro_digital/app/login/_children/register_austrotoken_login/presenter/screens/screens.dart';
import 'package:austro_digital/apps/ley_proteccion/models/args_for_law_terms_model.dart';
import 'package:austro_digital/core/widgets/inputs/terms_checkbox.dart';
import 'package:austro_digital/global_var.dart';
import 'package:ba_app_widgets/ba_components.dart';
import 'package:ba_mobile_core/ba_mobile_core.dart';
import 'package:ba_mobile_design_system/ba_mobile_design_system.dart';
import 'package:ba_mobile_utils/image_utils.dart';
import 'package:firebase_analytics_tracker/firebase_analytics_tracker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shimmer/shimmer.dart';
import 'package:sizer/sizer.dart';

List<Map<String, String>> items = [
  {
    'imagePath': ImageUtils.focoImage,
    'text': 'Tener buena iluminación.',
  },
  {
    'imagePath': ImageUtils.eyeglasses,
    'text': 'No uses lentes o accesorios.',
  },
  {
    'imagePath': ImageUtils.focusFace,
    'text': 'Enfoca tu cédula y rostro completo. Evita que esté borroso.',
  },
];

class CameraAccessPage extends StatefulWidget {
  static const String routeName = '/camera-access';

  const CameraAccessPage({super.key});

  @override
  State<CameraAccessPage> createState() => _CameraAccessPageState();
}

class _CameraAccessPageState extends State<CameraAccessPage>
    with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    GlobalVars().timeLastSession = DateTime.now();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);

    switch (state) {
      case AppLifecycleState.resumed:
        BlocProvider.of<CameraAccessBloc>(context).add(
          RequestCameraAccessEvent(),
        );
        break;
      case AppLifecycleState.paused:
        break;
      case AppLifecycleState.inactive:
        break;
      case AppLifecycleState.detached:
      default:
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider.value(
      value: BlocProvider.of<CameraAccessBloc>(context),
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Comprobar identidad'),
          centerTitle: false,
          bottom: const PreferredSize(
            preferredSize: Size.fromHeight(2.5),
            child: LinearProgressIndicator(
              color: BaColor.secondary,
              backgroundColor: Colors.transparent,
              value: 2 / 5,
            ),
          ),
        ),
        backgroundColor: BaColor.skyMist,
        body: BlocListener<CameraAccessBloc, CameraAccessState>(
          listener: (context, state) async {
            if (state is CameraAccessGrantedState) {
              // await Navigator.of(context).pushNamed(
              //   InfoScreen.routeName,
              //   arguments: InfoScreenArgs(
              //     appBarText: 'Comprobar identidad',
              //     title: 'Validación lista',
              //     messages: ['Hemos comprobado tu identidad exitosamente'],
              //     buttonText: 'Continuar',
              //     onPressed: () {
              //       Navigator.of(context).pushNamedAndRemoveUntil(
              //         CreateAustroTokenPinScreen.routeName,
              //         (route) => false,
              //       );
              //     },
              //     imagePath: imgCheckGlobal.path,
              //     imageColor: const Color(0xFF319E48),
              //   ),
              // );

              if (RemoteConfigService.instance
                  .getBool(RemoteConfigEnum.skipLifeTest)) {
                Navigator.of(context).pushNamed(
                  CreateAustroTokenPinScreen.routeName,
                );
              } else {
                Navigator.of(context).pushNamed(
                  //CreateAustroTokenPinScreen.routeName,
                  //AustroTokenActivatedScreen.routeName,
                  ProofOfLifeScreen.routeName,
                );
              }
            }
            if (state is CameraAccessDeniedState) {
              Navigator.pushNamed(
                context,
                InfoScreen.routeName,
                arguments: InfoScreenArgs(
                  appBarText: 'Comprobar identidad',
                  title: 'Acceso pendiente',
                  messages: [
                    'Es necesario los permisos de la cámara del dispositivo para continuar con el proceso de creación de cuenta.',
                  ],
                  buttonText: 'Permitir',
                  onPressed: () {
                    BlocProvider.of<CameraAccessBloc>(context).add(
                      RequestCameraAccessEvent(),
                    );
                    Navigator.of(context).pop();
                  },
                  imagePath: ImageUtils.notCamera,
                ),
              );
            }
            if (state is CameraAccessPermanentlyDeniedState) {
              Navigator.pushNamed(
                context,
                InfoScreen.routeName,
                arguments: InfoScreenArgs(
                  appBarText: 'Comprobar identidad',
                  title: 'Acceso pendiente',
                  messages: [
                    'Es necesario los permisos de la cámara del dispositivo para continuar con el proceso de creación de cuenta.',
                    'Puedes dar este permiso desde la configuración del sistema.',
                  ],
                  buttonText: 'Configuración',
                  onPressed: () {
                    context.read<CameraAccessBloc>().logEvent(
                          AnalyticsEvent.loginCameraAccessOnOpenConfiguration,
                        );
                    openAppSettings();

                    Navigator.of(context).pop();
                  },
                  imagePath: ImageUtils.notCamera,
                ),
              );
            }
          },
          child: const _Body(),
        ),
      ),
    );
    // return BlocProvider.value(
    //   value: BlocProvider.of<CameraAccessBloc>(context),
    //   child: BaScreenBase(
    //     hasGoBack: true,
    //     hasPadding: false,
    //     customBackgroundColor: BaColor.skyMist,
    //     appBarText: 'Comprobar identidad',
    //     child: BlocListener<CameraAccessBloc, CameraAccessState>(
    //       listener: (context, state) {

    //       },
    //       child: const _Body(),
    //     ),
    //   ),
    // );
  }
}

class _Body extends StatefulWidget {
  const _Body();

  @override
  State<_Body> createState() => _BodyState();
}

class _BodyState extends State<_Body> {
  bool _isChecked = true;
  bool _showTermsAndConditionsCheck = true;
  bool _isLoading = false;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _checkTermsAndConditions();
  }

  Future<void> _checkTermsAndConditions() async {
    if (context.read<CameraAccessBloc>().title ==
        'Recupera tu pin con identificación de tu rostro') {
      return;
    }
    bool accepted = false;
    if (!mounted) return;
    setState(() {
      _isLoading = true;
    });
    try {
      final CameraAccessBloc bloc = context.read<CameraAccessBloc>();
      accepted = await bloc.acceptedTermsAndConditions;
    } finally {
      if (mounted) {
        setState(() {
          _isLoading = false;
          _showTermsAndConditionsCheck = !accepted;
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
          child: ListView(
            children: [
              const SizedBox(height: 34.0),
              Image.asset(
                ImageUtils.cameraRounded,
                height: 190.0,
              ),
              const SizedBox(height: 50.0),
              H3(
                text: context.read<CameraAccessBloc>().title,
                color: BaColor.secondary,
                textAlign: TextAlign.center,
              ),
              const SizedBox(height: 20.0),
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 16.0),
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const H6(
                      text: 'Recuerda:',
                      color: BaColor.secondary,
                      textAlign: TextAlign.start,
                      fontWeight: FontWeight.w700,
                    ),
                    ...items
                        .map(
                          (item) => CustomRowWidget(
                            imagePath: item['imagePath']!,
                            text: item['text']!,
                          ),
                        )
                        .toList(),
                  ],
                ),
              ),
              GeneralVerticalSpace(
                customSpace: 2.h,
              ),
              GeneralVerticalSpace(
                customSpace: 12.h,
              ),
            ],
          ),
        ),
        if (_isLoading &&
            context.read<CameraAccessBloc>().title ==
                'Pediremos permiso para acceder a tu cámara')
          Shimmer.fromColors(
            baseColor: Colors.grey[300]!,
            highlightColor: Colors.grey[100]!,
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16.0),
              child: TermsCheckBox(
                checked: _isChecked,
                text: Text(
                  'He leído y acepto la Política de Privacidad y Protección de Datos Personales.',
                  style: TextStyle(
                    fontSize: 11.sp,
                    decoration: TextDecoration.underline,
                    fontWeight: FontWeight.w400,
                  ),
                ),
                onChange: (value) {},
              ),
            ),
          ),
        if (_showTermsAndConditionsCheck &&
            !_isLoading &&
            context.read<CameraAccessBloc>().title ==
                'Pediremos permiso para acceder a tu cámara')
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16.0),
            child: TermsCheckBox(
              checked: _isChecked,
              text: Text(
                'He leído y acepto la Política de Privacidad y Protección de Datos Personales.',
                style: TextStyle(
                  fontSize: 11.sp,
                  decoration: TextDecoration.underline,
                  fontWeight: FontWeight.w400,
                ),
              ),
              onChange: (value) {
                setState(() {
                  _isChecked = value ?? false;
                });
              },
              openTerms: () async {
                final bool? acepto = await Navigator.pushNamed<bool?>(
                  context,
                  TermsPdfPage.routeName,
                  arguments: ArgsForLawTermsModel(
                    pdfUrl: url,
                  ),
                );
                //final CameraAccessBloc bloc = context.read<CameraAccessBloc>();
                if (acepto != null && acepto) {
                  setState(() {
                    _isChecked = true;
                  });
                }
                //await _checkTermsAndConditions();
                if (!mounted) return;
                //setState(() => _isChecked = acepto ?? false);
              },
            ),
          ),
        const SizedBox(height: 16.0),
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16.0),
          child: BaButton(
            text: 'Continuar',
            onPressed: (_isLoading || !_isChecked) &&
                    context.read<CameraAccessBloc>().title !=
                        'Recupera tu pin con identificación de tu rostro'
                ? null
                : () async {
                    if (context.read<CameraAccessBloc>().title ==
                        'Recupera tu pin con identificación de tu rostro') {
                      BlocProvider.of<CameraAccessBloc>(context).add(
                        RequestCameraAccessEvent(),
                      );
                      return;
                    }
                    setState(() {
                      _isLoading = true;
                    });
                    final CameraAccessBloc bloc =
                        context.read<CameraAccessBloc>();
                    await bloc.acceptDataProtection();
                    setState(() {
                      _isLoading = false;
                    });
                    BlocProvider.of<CameraAccessBloc>(context).add(
                      RequestCameraAccessEvent(),
                    );
                  },
            backgroundColor: BaColor.primary,
          ),
        ),
        const SizedBox(height: 25.0),
      ],
    );
  }
}

class CustomRowWidget extends StatelessWidget {
  final String imagePath;
  final String text;

  const CustomRowWidget({
    Key? key,
    required this.imagePath,
    required this.text,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListTile(
      leading: Image.asset(
        imagePath,
      ),
      title: M3(
        text,
        color: BaColor.black,
        fontWeight: FontWeight.w400,
      ),
    );
  }
}

const url = 'https://www.bancodelaustro.com/politica-de-proteccion-de-datos';
```

</details>


### Screenshots or Video

<details open>
<summary>Screenshots / Video demonstration</summary>

Redmi Note 8 Pro (One time on Iphone 13, but anymore)

https://github.com/user-attachments/assets/ab7a1e36-d4ff-480f-95d7-8d00603c662e


</details>


### Logs

_No response_

### Flutter Doctor output

[✓] Flutter (Channel stable, 3.27.1, on macOS 15.2 24C101 darwin-arm64, locale en-EC)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 16.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2024.1)
[✓] IntelliJ IDEA Community Edition (version 2023.3.6)
[✓] VS Code (version 1.92.2)
[✓] Connected device (5 available)
    ! Error: Browsing on the local area network for iPhone. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac.
      The device must be opted into Developer Mode to connect wirelessly. (code -27)
    ! Error: Browsing on the local area network for iPhone de William. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac.
      The device must be opted into Developer Mode to connect wirelessly. (code -27)
[✓] Network resources

• No issues found!