1

I am trying to create a form that has a card and a login button: enter image description here

I have tried the following code:

import 'package:flutter/material.dart';

class LoginScreenDemo extends StatefulWidget {
  @override
  _LoginScreenState createState() => new _LoginScreenState();
 }

 class _LoginScreenState extends State<LoginScreenDemo> {
 @override
 Widget build(BuildContext context) {
 final email = TextFormField(
  keyboardType: TextInputType.emailAddress,
  autofocus: false,
  style: TextStyle(fontSize: 25.0),
  decoration: InputDecoration(
    labelText: 'Email',
    contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
    border: OutlineInputBorder(borderRadius: BorderRadius.circular(10.0)),
  ),
);

final password = TextFormField(
  obscureText: true,
  autofocus: false,
  style: TextStyle(fontSize: 25.0),
  decoration: InputDecoration(
    labelText: 'Password',
    contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
    border: OutlineInputBorder(borderRadius: BorderRadius.circular(10.0)),
  ),
);

final loginButton = Padding(
  padding: EdgeInsets.only(top: 10.0),
  child: RaisedButton(
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(20.0),
    ),
    onPressed: () {},
    padding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 30.0),
    color: Colors.lightBlueAccent,
    child: Text(
      'LOGIN',
      style: TextStyle(
        color: Colors.white,
        fontSize: 25.0,
        fontWeight: FontWeight.bold,
      ),
    ),
  ),
);

final goToSignUpScreen = Padding(
  padding: EdgeInsets.only(top: 5.0),
  child: FlatButton(
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(20.0),
    ),
    onPressed: () {
      Navigator.of(context).pushNamed('/signup');
    },
    child: Text(
      "New account? Sign Up",
      style: TextStyle(
        fontSize: 15.0,
      ),
    ),
  ),
);

final loginCard = Card(
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(15.0),
  ),
  color: Colors.white,
  elevation: 4.0,
  child: ListView(
    shrinkWrap: true,
    padding:
        EdgeInsets.only(top: 100.0, left: 50.0, right: 50.0, bottom: 75.0),
    children: <Widget>[
      email,
      SizedBox(height: 15.0),
      password,
    ],
  ),
);

final buttonsContainer = Container(
  alignment: Alignment.bottomCenter,
  padding: EdgeInsets.only(
    top: MediaQuery.of(context).orientation == Orientation.landscape
        ? MediaQuery.of(context).size.height * 0.35
        : MediaQuery.of(context).size.height * 0.26,
  ),
  child: Column(
    children: <Widget>[
      loginButton,
      goToSignUpScreen,
    ],
  ),
);

final backgroundContainer = Container(
  height: MediaQuery.of(context).size.height * 0.40,
  decoration: BoxDecoration(
    image: DecorationImage(
      image: AssetImage('assets/background_golf_course.jpeg'),
      fit: BoxFit.cover,
    ),
  ),
);

final formContainer = Container(
  alignment: Alignment.topCenter,
  padding: EdgeInsets.only(
    top: MediaQuery.of(context).size.height * 0.25,
    right: 20.0,
    left: 20.0,
  ),
  child: Container(
    width: MediaQuery.of(context).size.width * 0.75,
    child: Stack(
      children: <Widget>[
        loginCard,
        buttonsContainer,
      ],
    ),
  ),
);

return SafeArea(
  child: Container(
    color: Color(0xFFEEEEEE),
    child: Stack(
      children: <Widget>[
        backgroundContainer,
        formContainer,
      ],
    ),
  ),
);
}
}

I have placed the card and buttons in a stack widget and tried to place the buttons (as seen in buttonsContainer) above the card by defining their height and padding. As, can be seen, I need to define different padding for portrait and landscape modes and also, it breaks if the screen size changes. Is there a neater way to implement this?

Thanks

Timo Bähr
  • 1,826
  • 2
  • 22
  • 26
Varun
  • 31
  • 3
  • 1
    consensus on stackOverflow seems to be on MediaQueries... https://stackoverflow.com/questions/49704497/how-to-make-flutter-app-responsive-according-to-different-screen-size – Akber Iqbal Dec 29 '18 at 03:20
  • @Varun, I also face a similar kind of problem, have you found any solution? – Hitesh Gupta Sep 17 '19 at 07:39

1 Answers1

0

Container does have a property transform. Usage of this is an alternative to the top padding. Then buttonsContainer is placed relative to loginCard but is overlapping.

Widget buttonsContainer has a translation to the top.

    final buttonsContainer = Container(
      transform: Matrix4.translationValues(0.0, -34.0, 0.0),
      alignment: Alignment.bottomCenter,
      child: Column(
        children: <Widget>[
          loginButton,
          goToSignUpScreen,
        ],
      ),
    );

Widget formContainer then uses Column instead of Stack.

    final formContainer = Container(
      alignment: Alignment.topCenter,
      padding: EdgeInsets.only(
        top: MediaQuery.of(context).size.height * 0.25,
        right: 20.0,
        left: 20.0,
      ),
      child: Container(
        width: MediaQuery.of(context).size.width * 0.75,
        child: Column(
          children: <Widget>[
            loginCard,
            buttonsContainer,
          ],
        ),
      ),
    );
Timo Bähr
  • 1,826
  • 2
  • 22
  • 26