Flutter Responsive Login and Gradient Look

Flutter Responsive Login and Gradient Look

Assalamualaikum, Flutter.id – berikut adalah tampilan desain login yang responsive mengikuti ukuran device dengan warna gradient, dibuat oleh bang syajedul Islam dari Dhaka, Bangladesh.

Struktur FOlder

containerBoxDecoration.dart

import 'package:flutter/material.dart';

class ContainerBox {
  static getBoxDecoration({
    Color shadowColor,
    double blurRadius,
    BorderRadius borderRadius,
  }) {
    return BoxDecoration(
      boxShadow: [
        BoxShadow(
          color: shadowColor,
          blurRadius: blurRadius,
        ),
      ],
      borderRadius: borderRadius,
    );
  }
}

customTextField.dart

import 'package:flutter/material.dart';

class CustomTextField extends StatelessWidget {
  final String hintText;

  final double defFontSize;

  CustomTextField(this.defFontSize, this.hintText);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: 60,
      child: TextField(
        style: TextStyle(
            fontSize: defFontSize,
            fontWeight: FontWeight.bold,
            color: Colors.white),
        textAlign: TextAlign.center,
        decoration: InputDecoration(
          enabledBorder: OutlineInputBorder(
            borderRadius: BorderRadius.all(Radius.circular(6)),
            borderSide:
                BorderSide(width: 0, color: Colors.white.withOpacity(0.2)),
          ),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.all(Radius.circular(6)),
            borderSide:
                BorderSide(width: 0, color: Colors.white.withOpacity(0.2)),
          ),
          filled: true,
          fillColor: Colors.white.withOpacity(0.2),
          hintText: hintText,
          hintStyle: TextStyle(color: Colors.white),
        ),
      ),
    );
  }
}

gradientColor.dart

import 'package:flutter/material.dart';

class GradientColor {
  static getGradientColor() {
    return LinearGradient(
      begin: Alignment.bottomLeft,
      end: Alignment.topRight,
      colors: <Color>[
        Colors.deepPurple.withOpacity(0.8),
        Colors.purple.withOpacity(0.7),
        Colors.pink.withOpacity(0.7),
        Colors.red.withOpacity(0.7),
        Colors.orange.withOpacity(0.7),
      ],
    );
  }
}

gradientRaisedButton.dart

import 'package:flutter/material.dart';
import 'package:gradient_login_screens/reusableWidgets/gradientColor.dart';

class GradientRaisedButton extends StatelessWidget {
  final double fontSize;

  GradientRaisedButton(this.fontSize);
  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: 60,
      decoration: BoxDecoration(
        gradient: GradientColor.getGradientColor(),
        borderRadius: BorderRadius.circular(10),
      ),
      child: RaisedButton(
        color: Colors.transparent,
        highlightColor: Colors.pink.withOpacity(0.3),
        elevation: 0,
        focusElevation: 0,
        highlightElevation: 0,
        splashColor: Colors.white.withOpacity(0.2),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(10),
        ),
        child: Text(
          'LOGIN',
          style: TextStyle(
              color: Colors.white,
              fontSize: fontSize,
              fontWeight: FontWeight.bold),
        ),
        onPressed: () {
          // Perform some action
        },
      ),
    );
  }
}

1_topClipper.dart

import 'package:flutter/material.dart';

class ClipDesign extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ClipPath(
      clipper: TopClipper(),
      child: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(colors: [
            Colors.deepPurple.withOpacity(0.9),
            Colors.purple.withOpacity(0.8),
            Colors.pink.withOpacity(0.8),
            Colors.red.withOpacity(0.8),
            Colors.orange.withOpacity(0.8),
            //Colors.blue[400],
          ], begin: Alignment.bottomLeft, end: Alignment.topRight),
        ),
        height: MediaQuery.of(context).size.height / 2.8,
      ),
    );
  }
}

class TopClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    // This is where we decide what part of our image is going to be visible.
    var path = Path();
    path.lineTo(0.0, size.height);

    // //creating first curver near bottom left corner
    // var firstControlPoint = new Offset(size.width / 9, size.height - 30);
    // var firstEndPoint = new Offset(size.width / 7, size.height / 1.5);

    // path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
    //     firstEndPoint.dx, firstEndPoint.dy);

    // //creating second curver near center
    // var secondControlPoint = Offset(size.width / 4, size.height / 4);
    // var secondEndPoint = Offset(size.width / 2, size.height / 2);

    // path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
    //     secondEndPoint.dx, secondEndPoint.dy);

    //creating third curver near top right corner
    print(size.width / 2 + 100);
    var thirdControlPoint = Offset(size.width / 5, size.height / 5);

    var thirdEndPoint = Offset(size.width, size.height / 5);

    path.quadraticBezierTo(thirdControlPoint.dx, thirdControlPoint.dy,
        thirdEndPoint.dx, thirdEndPoint.dy);

    ///move to top right corner
    path.lineTo(size.width, 0.0);

    ///finally close the path by reaching start point from top right corner
    path.close();
    return path;
  }

  static const List<Color> orangeGradients = [
    Color(0xFFFF9844),
    Color(0xFFFE8853),
    Color(0xFFFD7267),
  ];

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) {
    return true;
  }
}

2_logo.dart

import 'package:flutter/material.dart';

class Logo extends StatelessWidget {
  final double iconSize;
  Logo(this.iconSize);
  @override
  Widget build(BuildContext context) {
    return Container(
      width: iconSize,
      height: iconSize,
      decoration: BoxDecoration(
        image: DecorationImage(
            image: AssetImage('assets/images/circleLogo.png'),
            fit: BoxFit.cover),
      ),
    );
  }
}

3_textFieldContainer.dart

import 'package:flutter/material.dart';
import 'package:gradient_login_screens/reusableWidgets/containerBoxDecoration.dart';
import 'package:gradient_login_screens/reusableWidgets/customTextField.dart';
import 'package:gradient_login_screens/reusableWidgets/gradientColor.dart';

class TextFieldContainer extends StatelessWidget {
  final double defFontSize;
  final spaceLeftRight;
  TextFieldContainer(this.defFontSize, this.spaceLeftRight);
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.only(left: spaceLeftRight, right: spaceLeftRight),
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              decoration: ContainerBox.getBoxDecoration(
                  shadowColor: Colors.black.withOpacity(0.0),
                  blurRadius: 13,
                  borderRadius: BorderRadius.circular(10)),
              child: Container(
                padding: EdgeInsets.only(
                  left: 10,
                  right: 10,
                  top: 50,
                  bottom: 50,
                ),
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(10),
                  gradient: GradientColor.getGradientColor(),
                ),
                child: Column(
                  children: <Widget>[
                    CustomTextField(defFontSize, 'MOBILE NUMBER'),
                    SizedBox(height: 30),
                    CustomTextField(defFontSize, 'PASSWORD'),
                  ],
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

//With card
// Card(
//       elevation: 0,
//       shape: RoundedRectangleBorder(
//         borderRadius: BorderRadius.circular(10),
//       ),
//       child: Container(
//         padding: EdgeInsets.all(15),
//         decoration: BoxDecoration(
//           borderRadius: BorderRadius.circular(10),
//           gradient: GradientColor.getGradientColor(),
//         ),
//         child: Column(
//           children: <Widget>[
//             CustomTextFieldCR(18, 'MOBILE NUMBER'),
//             SizedBox(height: 30),
//             CustomRaisedButtonCR(18),
//           ],
//         ),
//       ),
//     );

4_button.dart

import 'package:flutter/material.dart';
import 'package:gradient_login_screens/reusableWidgets/containerBoxDecoration.dart';
import 'package:gradient_login_screens/reusableWidgets/gradientRaisedButton.dart';

class Button extends StatelessWidget {
  final spaceLeftRight;
  final double defFontSize;
  Button(this.defFontSize, this.spaceLeftRight);
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.only(left: spaceLeftRight, right: spaceLeftRight),
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              decoration: ContainerBox.getBoxDecoration(
                  shadowColor: Colors.black.withOpacity(0.0),
                  blurRadius: 13,
                  borderRadius: BorderRadius.circular(10)),
              child: GradientRaisedButton(defFontSize),
            ),
          ],
        ),
      ),
    );
  }
}

loginScreen.dart

import 'package:flutter/material.dart';
import 'package:gradient_login_screens/screenParts/1_topClipper.dart';
import 'package:gradient_login_screens/screenParts/2_logo.dart';
import 'package:gradient_login_screens/screenParts/3_textFieldContainer.dart';
import 'package:gradient_login_screens/screenParts/4_button.dart';

class LoginScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var devSize = MediaQuery.of(context).size.shortestSide;
    var spaceLeftRight;
    double sBoxHeight;
    double defFontSize;
    double logoFontSize;
    double iconSize;
    double cardButtonGap;
    
    if (devSize <= 400) {
      spaceLeftRight = (devSize - devSize * 95 / 100);
      sBoxHeight = 20;
      defFontSize = 16;
      logoFontSize = 20;
      iconSize = 100;
      cardButtonGap = 20;
    } else if (devSize > 400 && devSize <= 700) {
      spaceLeftRight = (devSize - devSize * 95 / 100);
      sBoxHeight = 50;
      defFontSize = 18;
      logoFontSize = 26;
      iconSize = 150;
      cardButtonGap = 50;
    } else if (devSize > 700) {
      spaceLeftRight = (devSize - devSize * 85 / 100);
      sBoxHeight = 100;
      defFontSize = 20;
      logoFontSize = 36;
      iconSize = 250;
      cardButtonGap = 70;
    }
    //Note : Above configuration is to make it responsive. Yes there are other ways
    //but I like to do it by my own !

    return Scaffold(
      backgroundColor: Colors.white,
      body: Stack(
        children: <Widget>[
          //The clipper path used to design that you are seeing on top side !
          ClipDesign(),

          Container(
            alignment: Alignment.center,
            width: double.infinity,
            height: double.infinity,
            child: SingleChildScrollView(
              physics: ClampingScrollPhysics(),
              child: Container(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    //Logo
                    Logo(iconSize),

                    SizedBox(height: sBoxHeight), // Just a space

                    //App Name
                    Text(
                      'TEXT',
                      style: TextStyle(
                          fontSize: logoFontSize,
                          color: Colors.black.withOpacity(0.7),
                          fontWeight: FontWeight.bold),
                    ),

                    SizedBox(height: sBoxHeight), // Just a space

                    //Textfields
                    TextFieldContainer(defFontSize, spaceLeftRight),

                    // Space between Textfields and Login button
                    SizedBox(height: cardButtonGap),

                    //Login Button
                    Button(defFontSize, spaceLeftRight),
                  ],
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

main.dart

import 'package:flutter/material.dart';
import 'loginScreen.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: LoginScreen(),
    );
  }
}

Flutter Developer