Lyle Phillips
Lyle Phillips

Reputation: 11

Flutter Grey screen in release mode

Good Day All,

This is my first time working with flutter. I have two widgets that are working fine in debug mode with no errors in debug console when I run the app. However when I run the app as a container instance in azure then I get the grey screen for the login screen that has the said widgets on it. The exception in the browser console is also minified so I have no idea which part of the code causes it. When I remove the widgets from the login screen then there is no exception or gray screen. I'm also unable to replicate the error on local because when I build and run the image on local it works fine.

Please look at my two widgets maybe you guys can spot something that might be causing the error on release mode.

Below is my login page that contains said widgets.

import 'package:dcvc_flutter/features/home_page/presentation/pages/home_page.dart';
import 'package:dcvc_flutter/features/login/presentation/widgets/bottom_sheet.dart';
import 'package:dcvc_flutter/features/login/presentation/widgets/login_form.dart';
import 'package:flutter/material.dart';
import 'package:hexcolor/hexcolor.dart';

class LoginPage extends StatefulWidget {
  const LoginPage({Key? key}) : super(key: key);

  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: HexColor('D5EDE8'),
        leading: Padding(
          padding: const EdgeInsets.only(left: 20, top: 10, bottom: 10),
          child: Container(
            width: 34,
            height: 34,
            padding: const EdgeInsets.all(0),
            decoration: BoxDecoration(
              color: Colors.white,
              boxShadow: const [
                BoxShadow(
                  color: Colors.black26,
                  offset: Offset(0, 0.6),
                  blurRadius: 4.0,
                )
              ],
              borderRadius: BorderRadius.circular(8),
              border: Border.all(
                color: const Color(0x00000000),
                width: 1,
              ),
            ),
            child: IconButton(
              key: const Key('Back Button'),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => const HomePage()),
                );
              },
              icon: const Icon(Icons.arrow_back_ios_new),
              iconSize: 17,
              color: Colors.grey,
            ),
          ),
        ),
      ),
      body: Container(
        color: HexColor("D5EDE8"),
        width: double.infinity,
        padding: const EdgeInsets.fromLTRB(20, 60, 20, 0),
        child: Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Container(
              margin: const EdgeInsets.fromLTRB(15, 30, 15, 0),
              alignment: Alignment.topLeft,
              child: Text(
                "Welcome to your digitized Child Vaccine Card",
                style: TextStyle(
                  fontSize: 20,
                  fontWeight: FontWeight.w600,
                  color: HexColor("000000"),
                ),
              ),
            ),
            Container(
              alignment: Alignment.topLeft,
              margin: const EdgeInsets.fromLTRB(15, 25, 15, 60),
              child: Text(
                "Your health and safety in the palm of your hand",
                style: TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.w500,
                  color: HexColor("4AAE98"),
                ),
              ),
            ),
            const LoginForm(),
          ],
        ),
      ),
      bottomSheet: const BottomSheetCard(),
    );
  }
}

Below is the first widget Login Form

Ignore the import statement thats on two lines, its fine in my editor not sure why its like that on stack overflow.

import 'package:dcvc_flutter/core/bloc/authentication/auth_bloc.dart';
import 'package:dcvc_flutter/features/home_page/presentation/pages/home_page.dart';
import 'package:dcvc_flutter/features/login/presentation/bloc/login_bloc.dart';   
import'package:dcvc_flutter/features/login/presentation/widgets/
my_material_text_form_field.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/material.dart';
import 'package:formz/formz.dart';

class LoginForm extends StatefulWidget {
  const LoginForm({Key? key}) : super(key: key);

  @override
  _LoginFormState createState() => _LoginFormState();
}

class _LoginFormState extends State<LoginForm> {
  final _idnumberFocusNode = FocusNode();
  final _passwordFocusNode = FocusNode();

  @override
  void initState() {
    super.initState();
    _idnumberFocusNode.addListener(() {
      if (!_idnumberFocusNode.hasFocus) {
        context.read<LoginBloc>().add(LoginIdNumberUnfocused());
        FocusScope.of(context).requestFocus(_passwordFocusNode);
      }
    });
    _passwordFocusNode.addListener(() {
      if (!_passwordFocusNode.hasFocus) {
        context.read<LoginBloc>().add(LoginPasswordUnfocused());
      }
    });
  }

  @override
  void dispose() {
    _idnumberFocusNode.dispose();
    _passwordFocusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return BlocListener<LoginBloc, LoginState>(
      listener: (context, state) {
        if (state.status.isSubmissionSuccess) {
          ScaffoldMessenger.of(context)
            ..hideCurrentSnackBar()
            ..showSnackBar(
              SnackBar(
                content: Row(children: const <Widget>[
                  Icon(
                    Icons.check_circle_outline_rounded,
                    color: Color(0xff27b88d),
                  ),
                  Text(
                    'Successful Login.',
                    style: TextStyle(
                      color: Color(0xff27b88d),
                    ),
                  )
                ]),
                backgroundColor: Colors.white,
                behavior: SnackBarBehavior.floating,
                elevation: 5,
                margin: const EdgeInsets.all(5),
                shape: const RoundedRectangleBorder(
                  borderRadius: BorderRadius.all(Radius.circular(5)),
                ),
              ), 
            );
          context.read<AuthBloc>().add(AuthLogIn());
          Future.delayed(
            const Duration(seconds: 3),
            () {
              Navigator.pop(context);
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (_) => const HomePage(),
                ),
              );
            },
          );
        }
        if (state.status.isSubmissionFailure) {
          ScaffoldMessenger.of(context)
            ..hideCurrentSnackBar()
            ..showSnackBar(
              SnackBar(
                content: Row(children: const <Widget>[
                  Icon(
                    Icons.cancel_outlined,
                    color: Color.fromRGBO(218, 67, 54, 0.5),
                  ),
                  Text(
                    'Unsuccessful Login',
                    style: TextStyle(color: Colors.red),
                  )
                ]),
                backgroundColor: Colors.white,
                behavior: SnackBarBehavior.floating,
                elevation: 5,
                margin: const EdgeInsets.all(5),
                shape: const RoundedRectangleBorder(
                  borderRadius: BorderRadius.all(
                    Radius.circular(5),
                  ),
                ),
              ),
            );
        }
      },
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          IdNumberInput(focusNode: _idnumberFocusNode),
          const SizedBox(
            height: 16,
          ),
          PasswordInput(focusNode: _passwordFocusNode),
          const SizedBox(height: 16),
        ],
      ),
    );
  }
}

class IdNumberInput extends StatelessWidget {
  final FocusNode focusNode;

  const IdNumberInput({Key? key, required this.focusNode}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<LoginBloc, LoginState>(builder: (context, state) {
      return MyMaterialTextFormField(
        key: const Key('ID_TextField'),
        labelText: 'ID number *',
        errorText: state.idnumber.invalid ? '' : null,
        initialValue: state.idnumber.value,
        focusNode: focusNode,
        keyboardType: TextInputType.number,
        onChanged: (value) {
          context
              .read<LoginBloc>()
              .add(LoginIdentificationNumberChanged(value));
        },
        textInputAction: TextInputAction.next,
      );
    });
  }
}

class PasswordInput extends StatelessWidget {
  const PasswordInput({Key? key, required this.focusNode}) : super(key: key);

  final FocusNode focusNode;

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<LoginBloc, LoginState>(
      builder: (context, state) {
        var visible = state.passwordVisible;

        return MyMaterialTextFormField(
          initialValue: state.password.value,
          focusNode: focusNode,
          key: const Key('Password_TextField'),
          labelText: 'Password *',
          errorText: state.password.invalid ? 'Incorrect entry' : null,
          obscureText: !visible,
          onChanged: (value) {
            context.read<LoginBloc>().add(LoginPasswordChanged(value));
          },
          textInputAction: TextInputAction.done,
          suffixIcon: IconButton(
            onPressed: () =>
                context.read<LoginBloc>().add(LoginPasswordVisibilityChanged()),
            icon: Icon(
              visible ? Icons.visibility : Icons.visibility_off,
              color: Colors.grey,
            ),
          ),
        );
      },
    );
  }
 }

Below is the second widget bottomsheet card

import 'package:dcvc_flutter/features/login/presentation/bloc/login_bloc.dart';
import 'package:dcvc_flutter/features/register/presentation/pages/register_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:formz/formz.dart';
import 'package:hexcolor/hexcolor.dart';

class BottomSheetCard extends StatefulWidget {
  const BottomSheetCard({Key? key}) : super(key: key);

  @override
  State<BottomSheetCard> createState() => _BottomSheetCard();
}

class _BottomSheetCard extends State<BottomSheetCard> {
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 5),
      width: double.infinity,
      height: 120,
      child: Card(
        shape: const RoundedRectangleBorder(
          borderRadius: BorderRadius.only(
            topLeft: Radius.circular(30),
            topRight: Radius.circular(30),
          ),
        ),
        color: Colors.white,
        margin: const EdgeInsets.only(bottom: 0.0),
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 16),
          child: BlocBuilder<LoginBloc, LoginState>(
            builder: (context, state) {
              return Column(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Align(
                    alignment: Alignment.bottomCenter,
                    child: FractionallySizedBox(
                      widthFactor: 1,
                      child: ButtonTheme(
                        height: 46,
                        child: ElevatedButton(
                          onPressed: state.status.isValidated
                              ? () {
                                  context
                                      .read<LoginBloc>()
                                      .add(const LoginSubmitted());
                                }
                              : null,
                          child: const Text(
                            'Login',
                            style: TextStyle(
                              color: Color(0xfff8f8f8),
                              fontWeight: FontWeight.w600,
                              fontSize: 16.0,
                            ),
                          ),
                          style: ButtonStyle(
                            shadowColor:
                                MaterialStateProperty.resolveWith<Color>(
                              (Set<MaterialState> states) {
                                if (states.contains(MaterialState.pressed)) {
                                  return Colors.black;
                                } else if (states
                                    .contains(MaterialState.disabled)) {
                                  return Colors.black;
                                }
                                return Colors.black;
                              },
                            ),
                            backgroundColor:
                                MaterialStateProperty.resolveWith<Color>(
                              (Set<MaterialState> states) {
                                if (states.contains(MaterialState.pressed)) {
                                  return const Color(0xff27b88d);
                                } else if (states
                                    .contains(MaterialState.disabled)) {
                                  return const Color(0xFFD6D6D6);
                                }
                                return HexColor("27B88D");
                              },
                            ),
                            shape: MaterialStateProperty.all<
                                RoundedRectangleBorder>(RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(28),
                            )),
                            minimumSize: MaterialStateProperty.all<Size>(
                              const Size(10, 46),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      const Text(
                        "Don't have an account?",
                        style: TextStyle(color: Color(0xff6D6A6A)),
                      ),
                      RichText(
                        key: const Key('Top'),
                        text: TextSpan(
                          text: ' Register',
                          style: const TextStyle(
                            color: Color(0xff27b88d),
                          ),
                          recognizer: TapGestureRecognizer()
                            ..onTap = () {
                              Navigator.push(
                                context,
                                MaterialPageRoute(
                                  builder: (context) => const RegisterPage(),
                                ),
                              );
                            },
                         ),
                      )
                    ],
                  )
                ],
              );
            },
          ),
        ),
      ),
    );
  }
}

Thanks guys any help is much appreciated.

Upvotes: 0

Views: 2391

Answers (2)

Zozo
Zozo

Reputation: 193

If you use Firebase for authentication, make sure to run gradlew signingreport from the /android folder and copy SHA-1 & SHA-256 keys from release 'variant' into Firebase-Project Settings->SHA certificate fingerprints :)

Upvotes: 0

Giordany Orellana
Giordany Orellana

Reputation: 41

I had a similar issue and was able to disable parts of my code and narrowed the issue down to state management. Try disabling some of your code section by section and then try running flutter run --release in terminal. It takes a while but you will eventually find the issue.

Upvotes: 3

Related Questions