美文网首页
Flutter漂亮UI(Flutter-Auth)

Flutter漂亮UI(Flutter-Auth)

作者: litesky | 来源:发表于2020-06-07 18:04 被阅读0次
    image

    原项目可以在https://github.com/abuanwar072/Welcome-Login-Signup-Page-Flutter找到,官方录制了相应的视频在https://www.youtube.com/watch?v=ExKYjqgswJg&feature=youtu.be上,基于此编写学习的过程,本项目地址https://github.com/tianrandailove/flutter_auth

    实现欢迎页

    1. 首先定义主题的颜色,我们在lib目录下创建constant目录,并创建color_constant.dart 文件。
    import 'package:flutter/material.dart';
    
    const kPrimaryColor = Color(0xFF6F35A5); //深色
    const kPrimaryLightColor = Color(0xFFF1E6FF); //浅色
    
    1. 准备资源文件,在根目录下创建assets文件,并将资源拷贝到这里,并编辑pubspec.yaml文件配置资源文件的引用。
    flutter:
    
      # The following line ensures that the Material Icons font is
      # included with your application, so that you can use the icons in
      # the material Icons class.
      uses-material-design: true
    
      # To add assets to your application, add an assets section, like this:
      assets:
        - assets/images/
        - assets/icons/
    
    1. 需要使用flutter_svg渲染svg资源,编辑pubspec.yaml文件,引入flutter_svg包。
    dependencies:
      flutter:
        sdk: flutter
    
    
      # The following adds the Cupertino Icons font to your application.
      # Use with the CupertinoIcons class for iOS style icons.
      cupertino_icons: ^0.1.3
      flutter_svg: ^0.17.4
    
    dev_dependencies:
      flutter_test:
        sdk: flutter
    
    # For information on the generic Dart part of this file, see the
    # following page: https://dart.dev/tools/pub/pubspec
    
    1. 执行 pub get 命令。
    2. 在lib目录下创建pages/welcome目录。
    3. 先看下welcome页面的构成,整个页面由背景层和前景层组成,因此整个界面使用stack布局,使用Positioned配合布局背景层,column布局前景层。在pages/welcome目录下创建components目录(存放背景层和前景层)。
    4. 在components目录下创建background.dart 文件,该文件用于渲染welcome页面背景。
    import 'package:flutter/material.dart';
    
    class Background extends StatelessWidget{
      final Widget child;
    
      const Background({Key key,@required this.child}):super(key:key);
    
      @override
      Widget build(BuildContext context) {
        Size size = MediaQuery.of(context).size;
        return Container(
          height: size.height,
          width: double.infinity,
          child: Stack(
            alignment: Alignment.center,
            children: <Widget>[
              Positioned(
                top: 0,
                left: 0,
                child: Image.asset("assets/images/main_top.png",
                width: size.width*0.3,),
              ),
              Positioned(
                bottom: 0,
                  left: 0,
                child: Image.asset("assets/images/main_bottom.png",
                width: size.width*0.2,),
              )
              ,
              child,
            ],
          ),
        );
      }
    
    }
    
    1. 修改main.dart文件,删除其他代码,只保留 main函数和MyApp类的代码,并替换home节点的内容
    import 'package:flutter/material.dart';
    import 'package:flutterauth/pages/welcome/components/background.dart';
    import 'package:flutterauth/pages/welcome/welcome.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Flutter Auth',
          theme: ThemeData(
            // This is the theme of your application.
            //
            // Try running your application with "flutter run". You'll see the
            // application has a blue toolbar. Then, without quitting the app, try
            // changing the primarySwatch below to Colors.green and then invoke
            // "hot reload" (press "r" in the console where you ran "flutter run",
            // or simply save your changes to "hot reload" in a Flutter IDE).
            // Notice that the counter didn't reset back to zero; the application
            // is not restarted.
            primarySwatch: Colors.blue,
            // This makes the visual density adapt to the platform that you run
            // the app on. For desktop platforms, the controls will be smaller and
            // closer together (more dense) than on mobile platforms.
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: Scaffold(
            body: Background(
              child: Center(
                child: Text('WELCOME'),
              ),
            ),
          ),
        );
      }
    }
    
    1. 运行App,如下:
    image
    1. 在lib目录下创建widgets目录,在widgets目录下创建rounded_button.dart文件,这里实现一个圆角按钮,内容如下。
    import 'package:flutter/material.dart';
    import 'package:flutterauth/constant/color_constant.dart';
    
    class RoundedButton extends StatelessWidget {
      final String text;
      final Function press;
      final Color color, textColor;
    
      const RoundedButton(
          {Key key,
          this.text,
          this.press,
          this.color = kPrimaryColor,
          this.textColor = Colors.white})
          : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        Size size = MediaQuery.of(context).size;
        return Container(
          margin: EdgeInsets.symmetric(
            vertical: 10,
          ),
          width: size.width * 0.8,
          child: ClipRRect(
            borderRadius: BorderRadius.circular(29),
            child: FlatButton(
              padding: EdgeInsets.symmetric(vertical: 20, horizontal: 40),
              color: color,
              onPressed: press,
              child: Text(
                text,
                style: TextStyle(color: textColor),
              ),
            ),
          ),
        );
      }
    }
    
    1. 接下来在components目录下创建body.dart 文件,该文件用于渲染前景层。
    import 'package:flutter/material.dart';
    import 'package:flutter_svg/svg.dart';
    import 'package:flutterauth/constant/color_constant.dart';
    import 'package:flutterauth/pages/login/login.dart';
    import 'package:flutterauth/pages/signup/sign_up.dart';
    import 'package:flutterauth/pages/welcome/components/background.dart';
    import 'package:flutterauth/pages/widgets/rounded_button.dart';
    
    class Body extends StatelessWidget{
      @override
      Widget build(BuildContext context) {
        Size size = MediaQuery.of(context).size;
        return Background(
            child: SingleChildScrollView(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text("WELCOME",
                  style: TextStyle(fontWeight:FontWeight.bold),),
                  SizedBox(height: size.height*0.05,),
                  SvgPicture.asset("assets/icons/chat.svg",height: size.height*0.45,),
                  SizedBox(height: size.height*0.05,),
                  RoundedButton(
                    text: "SIGN IN",
                    press: (){
                    },
                  ),
                  RoundedButton(
                    text:"SIGN UP",
                    color: kPrimaryLightColor,
                    textColor: Colors.black,
                    press:(){
                    },
                  )
                ],
              ),
            )
        );
      }
    }
    
    1. 修改main.dart文件,将Background节点的child设置成刚刚创建Body实例。
    home: Scaffold(
            body: Background(
              child:Body(),
            ),
          ),
    
    1. 运行App。
    image.png
    1. 在welcome目录下创建welcome.dart文件,将整个welcome页面的渲染内容放到这个文件中。
    import 'package:flutter/material.dart';
    import 'package:flutterauth/pages/welcome/components/body.dart';
    
    class Welcome extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Body(),
        );
      }
    }
    
    1. 修改main.dart文件的home节点为Welcome实例。
    Widget build(BuildContext context) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Flutter Auth',
          theme: ThemeData(
            // This is the theme of your application.
            //
            // Try running your application with "flutter run". You'll see the
            // application has a blue toolbar. Then, without quitting the app, try
            // changing the primarySwatch below to Colors.green and then invoke
            // "hot reload" (press "r" in the console where you ran "flutter run",
            // or simply save your changes to "hot reload" in a Flutter IDE).
            // Notice that the counter didn't reset back to zero; the application
            // is not restarted.
            primarySwatch: Colors.blue,
            // This makes the visual density adapt to the platform that you run
            // the app on. For desktop platforms, the controls will be smaller and
            // closer together (more dense) than on mobile platforms.
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: Welcome(),
        );
      }
    

    实现登录页

    1. 在pages目录下创建login目录,在login下创建components目录。
    2. 登录页面和欢迎页面一样,采用背景层和前景层的布局方式。
    3. 在components目录下创建background.dart文件实现背景层。
    import 'package:flutter/material.dart';
    
    class Background extends StatelessWidget {
      final Widget child; //前景层元素做为子元素
      const Background({Key key, @required this.child}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        Size size = MediaQuery.of(context).size;
        return Container(
          width: double.infinity,
          height: size.height,
          child: Stack(
            alignment: Alignment.center,
            children: <Widget>[
              Positioned(
                top: 0,
                left: 0,
                child: Image.asset(
                  "assets/images/main_top.png",
                  width: size.width * 0.35,
                ),
              ),
              Positioned(
                bottom: 0,
                right: 0,
                child: Image.asset(
                  "assets/images/login_bottom.png",
                  width: size.width * 0.4,
                ),
              ),
              child,
            ],
          ),
        );
      }
    }
    
    1. 在lib/widgets创建text_field_container.dart文件,实现一个文本框容器。
    import 'package:flutter/material.dart';
    import 'package:flutterauth/constant/color_constant.dart';
    
    class TextFieldContainer extends StatelessWidget {
      final Widget child;
    
      const TextFieldContainer({Key key, @required this.child}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        Size size = MediaQuery.of(context).size;
        return Container(
          margin: EdgeInsets.symmetric(vertical: 10),
          padding: EdgeInsets.symmetric(horizontal: 20, vertical: 5),
          width: size.width * 0.8,
          decoration: BoxDecoration(
              color: kPrimaryLightColor, borderRadius: BorderRadius.circular(29)),
          child: child,
        );
      }
    }
    
    1. 在lib/widgets下创建rounded_input_field.dart文件,实现一个自定义的文本输入框。
    import 'package:flutter/material.dart';
    import 'package:flutterauth/constant/color_constant.dart';
    import 'package:flutterauth/pages/widgets/text_field_container.dart';
    
    class RoundedInputField extends StatelessWidget {
      final String hintText;
      final IconData icon;
      final ValueChanged<String> onChanged;
    
      const RoundedInputField({
        Key key,
        this.hintText,
        this.icon = Icons.person,
        this.onChanged,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return TextFieldContainer(
          child: TextField(
            onChanged: onChanged,
            cursorColor: kPrimaryColor,
            decoration: InputDecoration(
              icon: Icon(icon,color: kPrimaryColor,),
              hintText: hintText,
              border: InputBorder.none,
            ),
          ),
        );
      }
    }
    
    1. 在lib/widgets下创建rounded_password_field.dart文件,实现一个人密码输入框。
    import 'package:flutter/material.dart';
    import 'package:flutterauth/constant/color_constant.dart';
    import 'package:flutterauth/pages/widgets/text_field_container.dart';
    
    class RoundedPasswordField extends StatelessWidget {
      final ValueChanged<String> onChanged;
    
      const RoundedPasswordField({
        Key key,
        this.onChanged,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return TextFieldContainer(
          child: TextField(
            obscureText: true,
            onChanged: onChanged,
            cursorColor: kPrimaryColor,
            decoration: InputDecoration(
              icon: Icon(
                Icons.lock,
                color: kPrimaryColor,
              ),
              hintText: "Password",
              border: InputBorder.none,
              suffixIcon: Icon(
                Icons.visibility,
                color: kPrimaryColor,
              ),
            ),
          ),
        );
      }
    }
    
    1. 在lib/widgets下创建account_check.dart文件,实现文案组件。
    import 'package:flutter/material.dart';
    import 'package:flutterauth/constant/color_constant.dart';
    
    class AccountCheck extends StatelessWidget {
      final bool login;
      final Function press;
    
      const AccountCheck({
        Key key,
        this.login = true,
        this.press,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              login ? "Don't have an Account ? " : "Already have an Account ? ",
              style: TextStyle(color: kPrimaryColor),
            ),
            GestureDetector(
              onTap: press,
              child: Text(
                login ? "Sign Up" : "Sign In",
                style: TextStyle(
                  color: kPrimaryColor,
                  fontWeight: FontWeight.bold,
                ),
              ),
            )
          ],
        );
      }
    }
    
    1. 在login/components目录下创建body.dart实现前景层渲染。
    import 'package:flutter/material.dart';
    import 'package:flutter_svg/flutter_svg.dart';
    import 'package:flutterauth/pages/login/components/background.dart';
    import 'package:flutterauth/pages/signup/sign_up.dart';
    import 'package:flutterauth/pages/widgets/account_check.dart';
    import 'package:flutterauth/pages/widgets/rounded_button.dart';
    import 'package:flutterauth/pages/widgets/rounded_input_field.dart';
    import 'package:flutterauth/pages/widgets/rounded_password_field.dart';
    
    class Body extends StatelessWidget {
      const Body({Key key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        Size size = MediaQuery.of(context).size;
        return Background(
          child: SingleChildScrollView(
            child: Column(
              children: <Widget>[
                Text(
                  "LOGIN",
                  style: TextStyle(fontWeight: FontWeight.bold),
                ),
                SizedBox(
                  height: size.height * 0.03,
                ),
                SvgPicture.asset(
                  "assets/icons/login.svg",
                  height: size.height * 0.35,
                ),
                SizedBox(
                  height: size.height * 0.03,
                ),
                RoundedInputField(
                  hintText: "Your Email",
                  onChanged: (value) {},
                ),
                RoundedPasswordField(
                  onChanged: (value) {},
                ),
                RoundedButton(
                  text: "LOGIN",
                  press: () {},
                ),
                SizedBox(
                  height: size.height * 0.03,
                ),
                AccountCheck(
                  press: () {
                  },
                )
              ],
            ),
          ),
        );
      }
    }
    
    1. 在login目录下创建login.dart文件,渲染整个登录页面。
    import 'package:flutter/material.dart';
    import 'package:flutterauth/pages/login/components/body.dart';
    
    class Login extends StatelessWidget{
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Body(),
        );
      }
    }
    
    1. 修改lib/pages/welcome/components/body.dart文件,修改登录按钮的点击事件,添加登录页的路由。
    RoundedButton(
                    text: "SIGN IN",
                    press: (){
                      Navigator.push(context, MaterialPageRoute(
                        builder: (context){
                          return Login();
                        }
                      ));
                    },
                  ),
    
    1. 运行APP,并点击登录按钮,会跳转到登录页面。
    image.png

    实现注册页

    1. 在pages目录下创建signup目录,在signup下创建components目录。
    2. 注册页面也是采用背景层和前景层的布局方式。
    3. 在components目录下创建background.dart文件实现背景层。
    import 'package:flutter/material.dart';
    
    class Background extends StatelessWidget {
      final Widget child;
    
      const Background({
        Key key,
        @required this.child,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        Size size = MediaQuery.of(context).size;
        return Container(
          height: size.height,
          width: double.infinity,
          child: Stack(
            alignment: Alignment.center,
            children: <Widget>[
              Positioned(
                top: 0,
                left: 0,
                child: Image.asset(
                  "assets/images/signup_top.png",
                  width: size.width * 0.35,
                ),
              ),
              Positioned(
                bottom: 0,
                left: 0,
                child: Image.asset(
                  "assets/images/main_bottom.png",
                  width: size.width * 0.25,
                ),
              ),
              child,
            ],
          ),
        );
      }
    }
    
    1. 在components目录下创建or_deivider.dart文件,实现分割线。
    import 'package:flutter/material.dart';
    import 'package:flutterauth/constant/color_constant.dart';
    
    class OrDivider extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        Size size = MediaQuery.of(context).size;
        return Container(
          margin: EdgeInsets.symmetric(vertical: size.height * 0.02),
          width: size.width * 0.8,
          child: Row(
            children: <Widget>[
              buildDivider(),
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 10),
                child: Text(
                  "OR",
                  style: TextStyle(
                    color: kPrimaryColor,
                    fontWeight: FontWeight.w600,
                  ),
                ),
              ),
              buildDivider(),
            ],
          ),
        );
      }
    
      Expanded buildDivider() {
        return Expanded(
          child: Divider(
            color: Color(0xffd9d9d9),
            height: 1.5,
          ),
        );
      }
    }
    
    1. 在components目录下创建socal_icon.dart文件,用于实现社交icon渲染。
    import 'package:flutter/material.dart';
    import 'package:flutter_svg/flutter_svg.dart';
    import 'package:flutterauth/constant/color_constant.dart';
    
    class SocalIcon extends StatelessWidget {
      final String iconSrc;
      final Function press;
    
      const SocalIcon({
        Key key,
        this.press,
        this.iconSrc,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: press,
          child: Container(
            margin: EdgeInsets.symmetric(horizontal: 10),
            padding: EdgeInsets.all(20),
            decoration: BoxDecoration(
              border: Border.all(width: 2, color: kPrimaryLightColor),
              shape: BoxShape.circle,
            ),
            child: SvgPicture.asset(
              iconSrc,
              height: 20,
              width: 20,
            ),
          ),
        );
      }
    }
    
    1. 在components目录下创建body.dart文件实现前景层。
    import 'package:flutter/material.dart';
    import 'package:flutter_svg/flutter_svg.dart';
    import 'package:flutterauth/pages/login/login.dart';
    import 'package:flutterauth/pages/signup/components/background.dart';
    import 'package:flutterauth/pages/signup/components/or_divider.dart';
    import 'package:flutterauth/pages/signup/components/socal_icon.dart';
    import 'package:flutterauth/pages/widgets/account_check.dart';
    import 'package:flutterauth/pages/widgets/rounded_button.dart';
    import 'package:flutterauth/pages/widgets/rounded_input_field.dart';
    import 'package:flutterauth/pages/widgets/rounded_password_field.dart';
    
    class Body extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        Size size = MediaQuery.of(context).size;
        return Background(
          child: SingleChildScrollView(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  "SIGNUP",
                  style: TextStyle(fontWeight: FontWeight.bold),
                ),
                SizedBox(
                  height: size.height * 0.03,
                ),
                SvgPicture.asset(
                  "assets/icons/signup.svg",
                  height: size.height * 0.35,
                ),
                RoundedInputField(
                  hintText: "Your Email",
                  onChanged: (value) {},
                ),
                RoundedPasswordField(
                  onChanged: (value) {},
                ),
                RoundedButton(
                  text: "SIGNUP",
                  press: () {},
                ),
                SizedBox(
                  height: size.height * 0.03,
                ),
                AccountCheck(
                  login: false,
                  press: () {
                  },
                ),
                OrDivider(),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    SocalIcon(
                      iconSrc: "assets/icons/facebook.svg",
                      press: () {},
                    ),
                    SocalIcon(
                      iconSrc: "assets/icons/twitter.svg",
                      press: () {},
                    ),
                    SocalIcon(
                      iconSrc: "assets/icons/google-plus.svg",
                      press: () {},
                    )
                  ],
                )
              ],
            ),
          ),
        );
      }
    }
    
    1. 在signup目录下创建sign_up.dart文件,渲染整个注册页面。
    import 'package:flutter/material.dart';
    
    import 'components/body.dart';
    
    class SignUp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Body(),
        );
      }
    }
    
    1. 修改lib/pages/welcome/components/body.dart文件,为注册按钮添加点击事件,添加注册页的路由。
    RoundedButton(
                    text:"SIGN UP",
                    color: kPrimaryLightColor,
                    textColor: Colors.black,
                    press:(){
                      Navigator.push(context, MaterialPageRoute(
                        builder: (context){
                          return SignUp();
                        }
                      ));
                    },
                  )
    
    1. 运行App,点击注册按钮即可进入注册页面。


      image.png

    注册页和登录页跳转

    1. 修改lib/pages/login/components/body.dart文件,添加跳转注册页逻辑。
    AccountCheck(
                  press: () {
                    Navigator.push(context, MaterialPageRoute(builder: (context) {
                      return SignUp();
                    }));
                  },
                )
    
    1. 修改lib/pages/signup/components/body.dart文件,添加跳转登录页逻辑。
    AccountCheck(
                  login: false,
                  press: () {
                    Navigator.push(context, MaterialPageRoute(builder: (context) {
                      return Login();
                    }));
                  },
                )
    
    1. 运行App,可以在注册页和登录页互相跳转。

    相关文章

      网友评论

          本文标题:Flutter漂亮UI(Flutter-Auth)

          本文链接:https://www.haomeiwen.com/subject/juactktx.html