Raees Ali
Raees Ali

Reputation: 39

Expanded widgets inside column shrink when keyboard gets popped out

I'm working on a simple design for a login screen that has some content to display. The design looks perfect, as per the requirements.

But the issue is that when the keyboard is popped out, every widget's internal vertical spacing shrinks, and the widgets have no spacing.

Using SingleChildScrollView as parent of Column puts other errors which are mentioned here

Here's the code!

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:laundary_app/screens/signup_sreen.dart';
import 'package:laundary_app/utils/helpers/constants.dart';
import 'package:laundary_app/widgets/custom/custom_elevated_button.dart';
import 'package:laundary_app/widgets/custom/custom_text_field.dart';

class LoginScreen extends StatelessWidget {
  static const String routeName = '/login';

  const LoginScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: CustomScrollView(
          slivers: [
            SliverFillRemaining(
              hasScrollBody: false,
              child: Padding(
                padding: const EdgeInsets.only(
                  top: Constants.fullPagePadding,
                  left: Constants.fullPagePadding,
                  right: Constants.fullPagePadding,
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    SvgPicture.asset(
                      'assets/vectors/sign_in.svg',
                      height: 150,
                      fit: BoxFit.fitHeight,
                    ),
                    const Expanded(flex: 3, child: SizedBox()),
                    const Text(
                      'Welcome back!',
                      textAlign: TextAlign.center,
                      style: TextStyle(
                        fontSize: 30,
                        fontWeight: FontWeight.bold,
                        fontFamily: 'Poppins',
                      ),
                    ),
                    const Expanded(
                      child: SizedBox(),
                      flex: 2,
                    ),
                    CustomTextField(
                      hint: '[email protected]',
                      title: 'E-mail address',
                      controller: TextEditingController(),
                      onSubmitted: (value) {},
                      suffix: const Icon(Icons.alternate_email),
                    ),
                    const Expanded(child: SizedBox()),
                    CustomTextField(
                      hint: 'Password',
                      title: 'Password',
                      controller: TextEditingController(),
                      onSubmitted: (value) {},
                      obscureText: true,
                      suffix: IconButton(
                        icon: const Icon(Icons.remove_red_eye_outlined),
                        onPressed: () {},
                      ),
                    ),
                    const Expanded(child: SizedBox()),
                    Align(
                      alignment: Alignment.centerRight,
                      child: TextButton(
                        onPressed: () {},
                        child: const Text('Forget Password'),
                      ),
                    ),
                    buildORDivider(),
                    const Expanded(child: SizedBox()),
                    buildSocialMediaButtons(),
                    const Expanded(flex: 2, child: SizedBox()),
                    CustomElevatedButton(
                      text: 'Log in',
                      icon: Icons.arrow_forward_sharp,
                      onTap: () {},
                    ),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        const Text('Don\'t have an account'),
                        TextButton(
                          onPressed: () => Navigator.of(context)
                              .pushNamed(SignUpScreen.routeName),
                          child: const Text('Sign Up'),
                        ),
                      ],
                    )
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget buildORDivider() {
    return Row(
      children: const [
        Expanded(child: Divider(thickness: 1.5)),
        Padding(
          padding: EdgeInsets.symmetric(horizontal: 16.0),
          child: Text('or'),
        ),
        Expanded(child: Divider(thickness: 1.5)),
      ],
    );
  }

  Widget buildSocialMediaButtons() {
    // <a href="https://www.flaticon.com/free-icons/google" title="google icons">Google icons created by Freepik - Flaticon</a>
    // <a href="https://www.flaticon.com/free-icons/facebook" title="facebook icons">Facebook icons created by Fathema Khanom - Flaticon</a>
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        SocialMediaLoginButtonWidget(
          imagePath: 'assets/images/google.png',
          onPressed: () {},
        ),
        const SizedBox(width: 30),
        SocialMediaLoginButtonWidget(
          imagePath: 'assets/images/facebook.png',
          onPressed: () {},
        ),
      ],
    );
  }
}

class SocialMediaLoginButtonWidget extends StatelessWidget {
  const SocialMediaLoginButtonWidget(
      {Key? key, required this.imagePath, required this.onPressed})
      : super(key: key);

  final String imagePath;`enter code here`
  final VoidCallback onPressed;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 60,
      padding: const EdgeInsets.all(12.0),
      decoration: BoxDecoration(
        border: Border.all(color: Colors.grey),
        borderRadius: BorderRadius.circular(Constants.borderRadius),
      ),
      child: Image.asset(
        imagePath,
      ),
    );
  }
}

As a side note, here's the output of both scenarios as well.

Before keyboard is popped out

After keyboard

Upvotes: 1

Views: 441

Answers (3)

Berna
Berna

Reputation: 3

To avoid that, just put

resizeToAvoidBottomInset: false,

in your Scaffold()

Upvotes: 0

Nikita Shadkov
Nikita Shadkov

Reputation: 650

I would suggest you using ConstrainedBox instead of SizedBox to set minimum height

ConstrainedBox(
  constraints: new BoxConstraints(
    minHeight: 5.0,
  ),
),

original answer: link

Upvotes: 1

raw-chicken
raw-chicken

Reputation: 416

The expanded widgets are working as they are intended, expanding to fill the space that is available. When you have no space, they will shrink. If you want the space to remain and just scroll instead of squishing the expanded widgets, don't use the expanded widgets. Either use padding or just remove the Expanded widget and define whatever height you want inside the SizedBox.

const Expanded(child: SizedBox()),

SizedBox(height: 16),

If the reason you were using Expanded is because you wanted spacing proportional to screen size, you can also use MediaQuery.of(context).size.height to calculate the padding you need.

Upvotes: 0

Related Questions