Reputation: 39
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.
Upvotes: 1
Views: 441
Reputation: 3
To avoid that, just put
resizeToAvoidBottomInset: false,
in your Scaffold()
Upvotes: 0
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
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