Fluent news client – 03 static routing, component extraction, login and registration interface

Time:2021-10-18

Fluent news client - 03 static routing, component extraction, login and registration interface

Station B video

https://www.bilibili.com/vide…

Objectives of this section

  • Static routing
  • Shaded oval Icon
  • Input validity verification
  • Component extraction method
  • General components, business components
  • Program directory organization
  • Extract transparent navigation bar
  • Toast prompt component

1 static routing

1.1 define static routing

  • Landing page lib / pages / sign_ in/sign_ in.dart
  • Registration page lib / pages / sign_ up/sign_ up.dart
  • Static routing lib / routes.dart
import 'package:flutter_ducafecat_news/pages/sign_in/sign_in.dart';
import 'package:flutter_ducafecat_news/pages/sign_up/sign_up.dart';

///Static routing
var staticRoutes = {
  "/ sign in": (context) = > signinpage(), // login
  "/ sign up": (context) = > signuppage(), // registration
};

1.2 registering static routes

  • lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_ducafecat_news/pages/welcome/welcome.dart';
import 'package:flutter_ducafecat_news/routes.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ducafecat.tech',
      home: WelcomePage(),
      routes: staticRoutes,
      debugShowCheckedModeBanner: false,
    );
  }
}

2 login interface

2.1 maintaining color constants

  • lib/common/values/colors.dart
import 'dart:ui';

class AppColors {
  ///Main background white
  static const Color primaryBackground = Color.fromARGB(255, 255, 255, 255);

  ///Main text gray
  static const Color primaryText = Color.fromARGB(255, 45, 45, 47);

  ///Main control - background blue
  static const Color primaryElement = Color.fromARGB(255, 41, 103, 255);

  ///Main control - text white
  static const Color primaryElementText = Color.fromARGB(255, 255, 255, 255);

  // *****************************************

  ///Second control - background color light gray
  static const Color secondaryElement = Color.fromARGB(255, 246, 246, 246);

  ///Second control - text light blue
  static const Color secondaryElementText = Color.fromARGB(255, 41, 103, 255);

  // *****************************************

  ///The third control - background color, graphite
  static const Color thirdElement = Color.fromARGB(255, 45, 45, 47);
}

2.2 program structure

  • lib/pages/sign_in/sign_in.dart
import 'package:flutter/material.dart';
import 'package:flutter_ducafecat_news/common/utils/utils.dart';
import 'package:flutter_ducafecat_news/common/values/values.dart';
import 'package:flutter_ducafecat_news/common/widgets/widgets.dart';

class SignInPage extends StatefulWidget {
  SignInPage({Key key}) : super(key: key);

  @override
  _SignInPageState createState() => _SignInPageState();
}

class _SignInPageState extends State<SignInPage> {

  // logo
  Widget _buildLogo() {
    return Container();
  }

  //Login form
  Widget _buildInputForm() {
    return Container();
  }

  //Third party login
  Widget _buildThirdPartyLogin() {
    return Container();
  }

  //Register button
  Widget _buildSignupButton() {
    return Container();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: Center(
        child: Column(
          children: <Widget>[
            _buildLogo(),
            _buildInputForm(),
            Spacer(),
            _buildThirdPartyLogin(),
            _buildSignupButton(),
          ],
        ),
      ),
    );
  }
}

2.3 draw a shaded oval icon

  • lib/pages/sign_in/sign_in.dart
// logo
  Widget _buildLogo() {
    return Container(
      width: duSetWidth(110),
      Margin: edgeinsets. Only (top: dusetheight (40 + 44.0)), // top system bar 44px
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Container(
            height: duSetWidth(76),
            width: duSetWidth(76),
            margin: EdgeInsets.symmetric(horizontal: duSetWidth(15)),
            child: Stack(
              alignment: Alignment.center,
              children: [
                Positioned(
                  left: 0,
                  top: 0,
                  right: 0,
                  child: Container(
                    height: duSetWidth(76),
                    decoration: BoxDecoration(
                      color: AppColors.primaryBackground,
                      boxShadow: [
                        Shadows.primaryShadow,
                      ],
                      borderRadius: BorderRadius.all(
                          Radius. Circular (dusetwidth (76 * 0.5)), // 50% of the parent container
                    ),
                    child: Container(),
                  ),
                ),
                Positioned(
                  top: duSetWidth(13),
                  child: Image.asset(
                    "assets/images/logo.png",
                    fit: BoxFit.none,
                  ),
                ),
              ],
            ),
          ),
          Container(
            margin: EdgeInsets.only(top: duSetHeight(15)),
            child: Text(
              "SECTOR",
              textAlign: TextAlign.center,
              style: TextStyle(
                color: AppColors.primaryText,
                fontFamily: "Montserrat",
                fontWeight: FontWeight.w600,
                fontSize: duSetFontSize(24),
                height: 1,
              ),
            ),
          ),
          Text(
            "news",
            textAlign: TextAlign.center,
            style: TextStyle(
              color: AppColors.primaryText,
              fontFamily: "Avenir",
              fontWeight: FontWeight.w400,
              fontSize: duSetFontSize(16),
              height: 1,
            ),
          ),
        ],
      ),
    );
  }

2.4 extraction input box

  • lib/common/widgets/input.dart
///Input box
Widget inputTextEdit({
  @required TextEditingController controller,
  TextInputType keyboardType = TextInputType.text,
  String hintText,
  bool isPassword = false,
  double marginTop = 15,
}) {
  return Container(
    height: duSetHeight(44),
    margin: EdgeInsets.only(top: duSetHeight(marginTop)),
    decoration: BoxDecoration(
      color: AppColors.secondaryElement,
      borderRadius: Radii.k6pxRadius,
    ),
    child: TextField(
      controller: controller,
      keyboardType: keyboardType,
      decoration: InputDecoration(
        hintText: hintText,
        contentPadding: EdgeInsets.fromLTRB(20, 10, 0, 9),
        border: InputBorder.none,
      ),
      style: TextStyle(
        color: AppColors.primaryText,
        fontFamily: "Avenir",
        fontWeight: FontWeight.w400,
        fontSize: duSetFontSize(18),
      ),
      maxLines: 1,
      AutoCorrect: false, // AutoCorrect
      Obscuretext: ispassword, // hide the input content and password box
    ),
  );
}

2.5 draw flat button

  • lib/common/widgets/button.dart
///Flat fillet button
Widget btnFlatButtonWidget({
  @required VoidCallback onPressed,
  double width = 140,
  double height = 44,
  Color gbColor = AppColors.primaryElement,
  String title = "button",
  Color fontColor = AppColors.primaryElementText,
  double fontSize = 18,
  String fontName = "Montserrat",
  FontWeight fontWeight = FontWeight.w400,
}) {
  return Container(
    width: duSetWidth(width),
    height: duSetHeight(height),
    child: FlatButton(
      onPressed: onPressed,
      color: gbColor,
      shape: RoundedRectangleBorder(
        borderRadius: Radii.k6pxRadius,
      ),
      child: Text(
        title,
        textAlign: TextAlign.center,
        style: TextStyle(
          color: fontColor,
          fontFamily: fontName,
          fontWeight: fontWeight,
          fontSize: duSetFontSize(fontSize),
          height: 1,
        ),
      ),
    ),
  );
}

2.6 extract social login button

  • lib/common/widgets/button.dart
///Third party button
Widget btnFlatButtonBorderOnlyWidget({
  @required VoidCallback onPressed,
  double width = 88,
  double height = 44,
  String iconFileName,
}) {
  return Container(
    width: duSetWidth(width),
    height: duSetHeight(height),
    child: FlatButton(
      onPressed: onPressed,
      shape: RoundedRectangleBorder(
        side: Borders.primaryBorder,
        borderRadius: Radii.k6pxRadius,
      ),
      child: Image.asset(
        "assets/images/icons-$iconFileName.png",
      ),
    ),
  );
}

2.7 package toast prompt box

  • lib/common/widgets/toast.dart
Future<bool> toastInfo({
  @required String msg,
  Color backgroundColor = Colors.black,
  Color textColor = Colors.white,
}) async {
  return await Fluttertoast.showToast(
    msg: msg,
    toastLength: Toast.LENGTH_SHORT,
    gravity: ToastGravity.TOP,
    timeInSecForIos: 1,
    backgroundColor: backgroundColor,
    textColor: textColor,
    fontSize: duSetFontSize(16),
  );
}

2.8 data validity test

  • lib/pages/sign_in/sign_in.dart
...
class _SignInPageState extends State<SignInPage> {

  //Email controller
  final TextEditingController _emailController = TextEditingController();
  //Password controller
  final TextEditingController _passController = TextEditingController();
...

  //Perform login operation
  _handleSignIn() {
    if (!duIsEmail(_emailController.value.text)) {
      Toastinfo (MSG: 'please input mail correctly');
      return;
    }
    if (!duCheckStringLength(_passController.value.text, 6)) {
      Toastinfo (MSG: 'password cannot be less than 6 digits');
      return;
    }
  }

...

  //Login form
  Widget _buildInputForm() {
    return Container(
      width: duSetWidth(295),
      // height: 204,
      margin: EdgeInsets.only(top: duSetHeight(49)),
      child: Column(
        children: [
          // email input
          inputTextEdit(
            controller: _emailController,
            keyboardType: TextInputType.emailAddress,
            hintText: "Email",
            marginTop: 0,
          ),
          // password input
          inputTextEdit(
            controller: _passController,
            keyboardType: TextInputType.visiblePassword,
            hintText: "Password",
            isPassword: true,
          ),

          //Registration, login, horizontal layout
          Container(
            height: duSetHeight(44),
            margin: EdgeInsets.only(top: duSetHeight(15)),
            child: Row(
              children: [
                //Register
                btnFlatButtonWidget(
                  onPressed: _handleNavSignUp,
                  gbColor: AppColors.thirdElement,
                  title: "Sign up",
                ),
                Spacer(),
                //Login
                btnFlatButtonWidget(
                  onPressed: _handleSignIn,
                  gbColor: AppColors.primaryElement,
                  title: "Sign in",
                ),
              ],
            ),
          ),
          // Spacer(),

          // Fogot password
          Container(
            height: duSetHeight(22),
            margin: EdgeInsets.only(top: duSetHeight(20)),
            child: FlatButton(
              onPressed: () => {},
              child: Text(
                "Fogot password?",
                textAlign: TextAlign.center,
                style: TextStyle(
                  color: AppColors.secondaryElementText,
                  fontFamily: "Avenir",
                  fontWeight: FontWeight.w400,
                  fontSize: duSetFontSize(16),
                  Height: 1, // set the descending height, otherwise the font sinks
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

3 registration interface

3.1 program structure

  • lib/pages/sign_up/sign_up.dart
import 'package:flutter/material.dart';
import 'package:flutter_ducafecat_news/common/utils/utils.dart';
import 'package:flutter_ducafecat_news/common/values/values.dart';
import 'package:flutter_ducafecat_news/common/widgets/widgets.dart';

class SignUpPage extends StatefulWidget {
  SignUpPage({Key key}) : super(key: key);

  @override
  _SignUpPageState createState() => _SignUpPageState();
}

class _SignUpPageState extends State<SignUpPage> {

  // logo
  Widget _buildLogo() {
    return Container();
  }

  //Registration form
  Widget _buildInputForm() {
    return Container();
  }

  //Third party
  Widget _buildThirdPartyLogin() {
    return Container();
  }

  //Have an account
  Widget _buildHaveAccountButton() {
    return Container();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      ...,
      body: Center(
        child: Column(
          children: <Widget>[
            Divider(height: 1),
            _buildLogo(),
            _buildInputForm(),
            Spacer(),
            _buildThirdPartyLogin(),
            _buildHaveAccountButton(),
          ],
        ),
      ),
    );
  }
}

3.2 transparent navigation bar

  • lib/common/widgets/app.dart
///Transparent background AppBar
Widget transparentAppBar({
  @required BuildContext context,
  List<Widget> actions,
}) {
  return AppBar(
    backgroundColor: Colors.transparent,
    elevation: 0,
    title: Text(''),
    leading: IconButton(
      icon: Icon(
        Icons.arrow_back,
        color: AppColors.primaryText,
      ),
      onPressed: () {
        Navigator.pop(context);
      },
    ),
    actions: actions,
  );
}
  • lib/pages/sign_up/sign_up.dart
@override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: transparentAppBar(
        context: context,
        actions: <Widget>[
          IconButton(
            icon: Icon(
              Icons.info_outline,
              color: AppColors.primaryText,
            ),
            onPressed: () {
              Toastinfo (MSG: 'this is the registration interface');
            },
          )
        ],
      ),

3.2 registration form

  • lib/pages/sign_up/sign_up.dart
//Registration form
  Widget _buildInputForm() {
    return Container(
      width: duSetWidth(295),
      // height: 204,
      margin: EdgeInsets.only(top: duSetHeight(49)),
      child: Column(
        children: [
          // fullName input
          inputTextEdit(
            controller: _fullnameController,
            keyboardType: TextInputType.text,
            hintText: "Full name",
            marginTop: 0,
          ),
          // email input
          inputTextEdit(
            controller: _emailController,
            keyboardType: TextInputType.emailAddress,
            hintText: "Email",
          ),
          // password input
          inputTextEdit(
            controller: _passController,
            keyboardType: TextInputType.visiblePassword,
            hintText: "Password",
            isPassword: true,
          ),

          //Create
          Container(
            height: duSetHeight(44),
            margin: EdgeInsets.only(top: duSetHeight(15)),
            child: btnFlatButtonWidget(
              onPressed: () {
                if (!duCheckStringLength(_fullnameController.value.text, 5)) {
                  Toastinfo (MSG: 'user name cannot be less than 5 digits');
                  return;
                }
                if (!duIsEmail(_emailController.value.text)) {
                  Toastinfo (MSG: 'please input mail correctly');
                  return;
                }
                if (!duCheckStringLength(_passController.value.text, 6)) {
                  Toastinfo (MSG: 'password cannot be less than 6 digits');
                  return;
                }
                Navigator.pop(context);
              },
              width: 295,
              fontWeight: FontWeight.w600,
              title: "Create an account",
            ),
          ),
          // Spacer(),

          // Fogot password
          Container(
            height: duSetHeight(22),
            margin: EdgeInsets.only(top: duSetHeight(20)),
            child: FlatButton(
              onPressed: _handleSignUp,
              child: Text(
                "Fogot password?",
                textAlign: TextAlign.center,
                style: TextStyle(
                  color: AppColors.secondaryElementText,
                  fontFamily: "Avenir",
                  fontWeight: FontWeight.w400,
                  fontSize: duSetFontSize(16),
                  Height: 1, // set the descending height, otherwise the font sinks
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

3.3 inspection effectiveness

  • lib/pages/sign_up/sign_up.dart
//Perform the registration operation
  _handleSignUp() {
    if (!duCheckStringLength(_fullnameController.value.text, 5)) {
      Toastinfo (MSG: 'user name cannot be less than 5 digits');
      return;
    }
    if (!duIsEmail(_emailController.value.text)) {
      Toastinfo (MSG: 'please input mail correctly');
      return;
    }
    if (!duCheckStringLength(_passController.value.text, 6)) {
      Toastinfo (MSG: 'password cannot be less than 6 digits');
      return;
    }
    Navigator.pop(context);
  }

3.4 social buttons

  • lib/pages/sign_up/sign_up.dart
//Third party
  Widget _buildThirdPartyLogin() {
    return Container(
      width: duSetWidth(295),
      margin: EdgeInsets.only(bottom: duSetHeight(40)),
      child: Column(
        children: <Widget>[
          // title
          Text(
            "Or sign in with social networks",
            textAlign: TextAlign.center,
            style: TextStyle(
              color: AppColors.primaryText,
              fontFamily: "Avenir",
              fontWeight: FontWeight.w400,
              fontSize: duSetFontSize(16),
            ),
          ),
          //Push button
          Padding(
            padding: EdgeInsets.only(top: duSetHeight(20)),
            child: Row(
              children: <Widget>[
                btnFlatButtonBorderOnlyWidget(
                  onPressed: () {},
                  width: 88,
                  iconFileName: "twitter",
                ),
                Spacer(),
                btnFlatButtonBorderOnlyWidget(
                  onPressed: () {},
                  width: 88,
                  iconFileName: "google",
                ),
                Spacer(),
                btnFlatButtonBorderOnlyWidget(
                  onPressed: () {},
                  width: 88,
                  iconFileName: "facebook",
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

3.5 return button

  • lib/pages/sign_up/sign_up.dart
//Back to previous page
  _handleNavPop() {
    Navigator.pop(context);
  }

  Widget _buildHaveAccountButton() {
    return Container(
      margin: EdgeInsets.only(bottom: duSetHeight(20)),
      child: btnFlatButtonWidget(
        onPressed: _handleNavPop,
        width: 294,
        gbColor: AppColors.secondaryElement,
        fontColor: AppColors.primaryText,
        title: "I have an account",
        fontWeight: FontWeight.w500,
        fontSize: 16,
      ),
    );
  }

Git code

https://github.com/ducafecat/…

Blue lake design draft

https://lanhuapp.com/url/lYuz1
Password: gskl

Blue lake charges now, so please upload XD design draft by yourself to view the tag
It’s difficult to share the commercial design documents directly. You can contact ducafecat through wechat

reference resources

video

Recommended Today

SQL exercise 20 – Modeling & Reporting

This blog is used to review and sort out the common topic modeling architecture, analysis oriented architecture and integration topic reports in data warehouse. I have uploaded these reports to GitHub. If you are interested, you can have a lookAddress:https://github.com/nino-laiqiu/TiTanI recorded a relatively complete development process in my hexo blog deployed on GitHub. You can […]