I’m Zero and today we are going to use Flutter to create the effect 👆 above

At a glance, um 🤔… Very beautiful… Very pen youte Buddha (Beautiful) 👍 and then a rough look 🤣 little brother, you bluff me? Isn’t it just a login page? Take a closer look at the wrong 😱, surprisingly there are so many knowledge points below 👇

Core knowledge

  • Container
  • Text
  • Image
  • Column
  • Row
  • Stack
  • SizedBox
  • TextField
  • Padding
  • Spacer
  • Positioned
  • GestureDetector
  • Divider
  • ClipPath
  • Path
  • Bezier curve
  • Pull the Flutter components away

To access the official document of Flutter directly after reading the article, like it and click the corresponding Widget 😏, (super thoughtful 💗)

  • After the first look, update forever 👏
  • All right, let’s get down to business

📖 Project introduction 📖

This is my second Speed Code video project, where you can learn the basics and advanced uses of these widgets and, more importantly, how to combine them flexibly to achieve the results of 👆 above.

If you think it is helpful, please like 👍. I will be more motivated to record and share more good Flutter content. Thank you for your like

Defining common topics

  • The size of the
/// theme/app_size.dart
import 'package:flutter/material.dart';

// Title text size
const double kTitleTextSize = 24;
// The size of the text
const double kBodyTextSize = 14;
// Button text size
const double kBtnTextSize = 18;
// Button fillet radius
const double kBtnRadius = 24;
// Input box border radius
const double kInputBorderRadius = 5;
/ / icon size
const double kIconSize = 24;
// Icon box size
const double kIconBoxSize = 56;
/ / Light words
const FontWeight kLightFontWeight = FontWeight.w300;
/ heavy/Medium word
const FontWeight kMediumFontWeight = FontWeight.w500;

Copy the code
  • color
/// theme/app_colors.dart
import 'package:flutter/widgets.dart';

// Background color
const Color kBgColor = Color(0xFFFEDCE0);
// Text color
const Color kTextColor = Color(0xFF3D0007);
// Button start color
const Color kBtnColorStart = Color(0xFFF89500);
// Button to end color
const Color kBtnColorEnd = Color(0xFFFA6B74);
// Button projection color
const Color kBtnShadowColor = Color(0x33D83131);
// Enter the box border color
const Color kInputBorderColor = Color(0xFFECECEC);

// Button gradient background color
const LinearGradient kBtnLinearGradient = LinearGradient(
  colors: [
    kBtnColorStart,
    kBtnColorEnd,
  ],
);

Copy the code
  • style
/// theme/app_style.dart
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'app_colors.dart';
import 'app_size.dart';

// Button projection
const List<BoxShadow> kBtnShadow = [
  BoxShadow(
    color: kBtnShadowColor,
    offset: Offset(0.8),
    blurRadius: 20,
  )
];

// Button text style
const TextStyle kBtnTextStyle = TextStyle(
  color: kBtnColorStart,
  fontSize: kBtnTextSize,
  fontWeight: kMediumFontWeight,
);

// Title text style
const TextStyle kTitleTextStyle = TextStyle(
  fontSize: kTitleTextSize,
  color: kTextColor,
  fontWeight: kMediumFontWeight,
);

// The content text style
const TextStyle kBodyTextStyle = TextStyle(
  fontSize: kBodyTextSize,
  color: kTextColor,
  fontWeight: kLightFontWeight,
);

// Input box border
OutlineInputBorder kInputBorder = OutlineInputBorder(
  borderRadius: BorderRadius.circular(5),
  borderSide: BorderSide(
    color: kInputBorderColor,
    width: 1,),);Copy the code

Building the welcome page

Draw header content

  • 1. Draw the head background
// WelBgHeader
Image.asset(
  'assets/images/bg_welcome_header.png'
)
Copy the code

  • 2. Draw App Icon
// AppIconWidget
Container(
  width: kIconBoxSize,
  height: kIconBoxSize,
  decoration: BoxDecoration(
    color: Colors.white,
    shape: BoxShape.circle,
  ),
  alignment: Alignment.center,
  child: Image.asset(
    'assets/icons/app_icon.png',
    width: 24,
    height: 32,),)Copy the code

  • 3. Draw the text under Icon
/// Icon Text
Positioned(
  top: 194,
  left: 40,
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      AppIconWidget(),
      SizedBox(height: 8),
      Text(
        'Sour',
        style: kTitleTextStyle,
      ),
      SizedBox(height: 8),
      Text(
        'Best drink\nreceipes',
        style: kBodyTextStyle,
      ),
    ],
  ),
),
Copy the code

  • 4. Set the overall background color
/// WelcomePage
Scaffold(
  backgroundColor: kBgColor,
  body: Column(
    children: [
      WelcomeHeaderWidget(),
    ],
  ),
)
Copy the code

Draw bottom content

Read the notes carefully. It’s important

  • 1. Draw the gradient background of the button
// Button gradient background color
const LinearGradient kBtnLinearGradient = LinearGradient(
  colors: [
    kBtnColorStart,
    kBtnColorEnd,
  ],
);
// Button projection
const List<BoxShadow> kBtnShadow = [
  BoxShadow(
    color: kBtnShadowColor,
    offset: Offset(0.8),
    blurRadius: 20,
  )
];
// Gradient button
// GradientBtnWidget
SizedBox(
  width: width,
  height: 48,
  child: GestureDetector(
    onTap: onTap,
    child: Container(
      decoration: BoxDecoration(
        // Set gradient
        gradient: kBtnLinearGradient,
        // Set the projection
        boxShadow: kBtnShadow,
		    // Set the radius of the fillet
        borderRadius: BorderRadius.circular(kBtnRadius),
      ),
      alignment: Alignment.center,
      child: child,
    ),
  ),
)
Copy the code
  • 2. Draw text
// Button text style
const TextStyle kBtnTextStyle = TextStyle(
  color: kBtnColorStart,
  fontSize: kBtnTextSize,
  fontWeight: kMediumFontWeight,
);
// White button text
// BtnTextWhiteWidget
Text(
  text,
  style: kBtnTextStyle.copyWith(
    color: Colors.white,
  ),
)
Copy the code
  • 3, combination
// Sign up button
GradientBtnWidget(
  width: 208,
  child: BtnTextWhiteWidget(text: 'Sign up'),
  onTap: () {},
)
Copy the code

  • 4. Draw the login button
// LoginBtnWidget
Container(
  height: 48,
  width: 208,
  decoration: BoxDecoration(
    // Set it to white
    color: Colors.white,
    // Set the radius of the fillet
    borderRadius: BorderRadius.circular(kBtnRadius),
    // Set the projection
    boxShadow: kBtnShadow,
  ),
  alignment: Alignment.center,
  child: Text(
    'Login',
    style: kBtnTextStyle,
  ),
)
Copy the code

  • 5. Add forgotten password text
// Forget the password
Text(
  'Forgot password? ',
  style: TextStyle(
    fontSize: 18,
    color: kTextColor,
  ),
)
Copy the code
  • 6. Draw the bottom social media third-party logins

// Login icon
class LoginTypeIconWidget extends StatelessWidget {
  const LoginTypeIconWidget({
    Key key,
    this.icon,
  }) : super(key: key);
  final String icon;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 10),
      child: Image.asset(
        icon,
        width: 16,
        height: 16,),); }}/ / horizontal
class LineWidget extends StatelessWidget {
  const LineWidget({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      child: Divider(color: kTextColor),
      width: 80,); }}/// combined
Row(
  children: [
    Spacer(),
    LineWidget(),
    LoginTypeIconWidget(icon: 'assets/icons/logo_ins.png'),
    LoginTypeIconWidget(icon: 'assets/icons/logo_fb.png'),
    LoginTypeIconWidget(icon: 'assets/icons/logo_twitter.png'),
    LineWidget(),
    Spacer(),
  ],
)
Copy the code

The login page

Draw header area

  • 1. Draw the background
Scaffold(
  // Set the background to white
  backgroundColor: Colors.white,
  body: Stack(
    children: [
      Image.asset(
        'assets/images/bg_login_header.png'),,),);Copy the code
  • 2. Draw the back button
// BackIcon
GestureDetector(
  onTap: () {
    / / return
    Navigator.pop(context);
  },
  child: Container(
    width: 56,
    height: 56,
    decoration: BoxDecoration(
      // White background
      color: Colors.white,
      // Set the circle
      shape: BoxShape.circle,
    ),
    // [this is important] set to center
    alignment: Alignment.center,
    child: Image.asset(
      'assets/icons/icon_back.png',
      width: 24,
      height: 24,),),)Copy the code

Draws the contents of the input area

  • 1. Draw text
// Login text content, you can see the global definition of the style above
Text(
  'Login',
  style: kTitleTextStyle,
),
SizedBox(height: 20),
Text(
  'Your Email',
  style: kBodyTextStyle,
),
Copy the code
  • 2. Draw the input box
// LoginInput
TextField(
  decoration: InputDecoration(
    // Default text
    hintText: hintText,
    / / frame
    border: kInputBorder,
    focusedBorder: kInputBorder,
    enabledBorder: kInputBorder,
    // The mail icon in front of the input box
    prefixIcon: Container(
      width: kIconBoxSize,
      height: kIconBoxSize,
      // [this is very important, again] otherwise it will pull up
      alignment: Alignment.center,
      child: Image.asset(
        prefixIcon,
        width: kIconSize,
        height: kIconSize,
      ),
    ),
    // Set the password style
    obscureText: obscureText,
    // Set the text style
    style: kBodyTextStyle.copyWith(
      fontSize: 18,),)Copy the code
  • 3. Combination style
// LoginBodyWidget - Column
SizedBox(height: 4),
LoginInput(
  hintText: 'Email',
  prefixIcon: 'assets/icons/icon_email.png',
),
SizedBox(height: 16),
Text(
  'Your Password',
  style: kBodyTextStyle,
),
SizedBox(height: 4),
LoginInput(
  hintText: 'Password',
  prefixIcon: 'assets/icons/icon_pwd.png',),Copy the code

  • 4. Draw the login button
// Login button
Row(
  children: [
    Spacer(),
    // Gradient background component
    GradientBtnWidget(
      child: Row(
        children: [
          SizedBox(width: 34),
          // White text
          BtnTextWhiteWidget(text: 'Login'),
          Spacer(),
          // Go to the right
          Image.asset(
            'assets/icons/icon_arrow_right.png',
            width: kIconSize,
            height: kIconSize,
          ),
          SizedBox(width: 24),
        ],
      ),
      width: 160,
      onTap: () {
        // Click login, here the simulation returnsNavigator.pop(context); },),,)Copy the code

支那

Drawing curve clipping

You can look at the overall path of the curve design and figure outSix control pointsFour coordinate points

  • P: coordinate point
  • C: control point
// We use path clipping
ClipPath(
  clipper: LoginCliper(),
  child: LoginBodyWidget(),
),

// Login page clipping curve
class LoginCliper extends CustomClipper<Path> {
  // First point
  Point p1 = Point(0.0.54.0);
  Point c1 = Point(20.0.25.0);
  Point c2 = Point(81.0.8.0);
  // The second point
  Point p2 = Point(160.0.20.0);
  Point c3 = Point(216.0.38.0);
  Point c4 = Point(280.0.73.0);
  // The third point
  Point p3 = Point(280.0.44.0);
  Point c5 = Point(280.0.11.0);
  Point c6 = Point(330.0.8.0);

  @override
  Path getClip(Size size) {
    // The fourth point
    Point p4 = Point(size.width, . 0);

    Path path = Path();
    // Move to the starting point
    path.moveTo(p1.x, p1.y);
    // Paragraph 1: Third-order Bezier curves
    path.cubicTo(c1.x, c1.y, c2.x, c2.y, p2.x, p2.y);
    // Paragraph 2: Third-order Bezier curves
    path.cubicTo(c3.x, c3.y, c4.x, c4.y, p3.x, p3.y);
    // Paragraph 3: Third-order Bezier curves
    path.cubicTo(c5.x, c5.y, c6.x, c6.y, p4.x, p4.y);
    / / the bottom right hand corner
    path.lineTo(size.width, size.height);
    / / the bottom left corner
    path.lineTo(0, size.height);
    / / closed
    path.close();
    return path;
  }

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    returnoldClipper.hashCode ! =this.hashCode; }}Copy the code

The final result



Where do these coordinates come from?

Some friends in station B asked, it is my negligence, supplement the following figure and instructions, you will understand.

  • The width and height of the entire clipped component is:375x491
  • Finally, according to the position of each point marked in the design draft, the coordinate points are calculated relative to the position of the component of the clipping region.
  • Calculate the following
// First point
p1 = Point(0.0.54.0);
c1 = Point(20.0.25.0);
c2 = Point(81.0.8.0);
// The second point
p2 = Point(160.0.20.0);
c3 = Point(216.0.38.0);
c4 = Point(280.0.73.0);
// The third point
p3 = Point(280.0.44.0);
c5 = Point(280.0.11.0);
c6 = Point(330.0.8.0);
// The fourth point
Point p4 = Point(size.width, . 0);
/ / the bottom right hand corner
p5 = Point(size.width, size.height);
/ / the bottom left corner
p6 = Point(. 0, size.height);
Copy the code

The source code

  • Base branch: defines the base global style, image, use their own practice
  • Master branch: The complete code corresponding to the video content
  • Update branch: It is continuously updated and optimized
  • GitHub- Flutter_DRINk_login_app GitHub- Flutter_DRINk_login_app

Last updated [2021-04-24]

  • 1. Video 5S small screen
  • 2. Add screen adaptation extension classes
  • 3, optimization of adaptive keyboard pop-up occlusion problem
  • 4. Change the password blocking character to *

video

It is recommended to clone the base branch code, according to the video themselves to knock a few times, can become their own things hands-on combat is the best way to quickly learn

  • BiliBili-(video content launch site)

About me

  • 15 to 18 years of useAndroidDo original smart hardware related App research and development
  • In May of ’18, I came into contact with him by chanceFlutterAnd then start self-study, you can seeweather_flutterIt is my introduction to Flutter practice. (I still think it is very suitable for Flutter practice.)
  • In August, 2018, under great pressure (Flutter was not released 1.0 at that time), I started to develop enterprise-level projects with Flutter and developed and maintained more than a dozen Flutter plugin packages (due to the lack of plugin resources at that time).
  • Up to now, I have led and participated in the launch of 4 enterprise-level productsFlutterApp, the accumulated users of an App I am currently in charge of120W+, the use ofFlutterIt was a great experience

Thank you

  • Thank youElizabeth ArosteguiVery beautiful blueprints. This is hersFigma home page
  • If you also have a great design drawing, then you can contact me to make an App to share with you

Pay attention to column

  • This article has been included in the column at 👇 below, you can follow it directly
  • Read more | The series continues to be updated

👏 please like ➕ and follow ➕ to forward. Please feel free to comment on 👇 if you have any questions. I will reply as soon as possible