学习Flutter近5天了,开始做一个App的入门项目,做一个登录界面:
会涉及到以下知识点:
各种Widget的使用包含Container、Text、Image等,MaterialPageRoute()的窗口调用等;效果如下(同时给学校和老师的公司打了个广告,不过没收钱,哈哈哈):
好,现在就开始吧,首先介绍下我的程序架构:
所有的程序都在lib文件夹下:
其他的constants.dart文件为自定义的颜色存储:
必要说明:文件的头引用是我自己的文件名,大家调用的时候不要忘记换成自己的:
sizedBox是我用来调节摆放位置用的
下面把各段代码奉上:
- main.dart:
import 'package:flutter/material.dart';
import 'package:llggflutter_app/Screens/Welcome/welcome_screen.dart';
import 'package:llggflutter_app/constants.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(
primaryColor: kPrimaryColor,
scaffoldBackgroundColor: Colors.white,
),
home: WelcomeScreen(),
);
}
}
2.welcome_screen.dart
import 'package:flutter/material.dart';
import 'package:llggflutter_app/Screens/Welcome/components/body.dart';
class WelcomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Body(),
);
}
}
3.constants.dart
import 'package:flutter/material.dart';
const kPrimaryColor = Color(0xFF6F35A5);
const kPrimaryLightColor = Color(0xFFF1E6FF);
- Welcome下的body.dart
import 'package:flutter/material.dart';
import 'package:llggflutter_app/Screens/Login/login_screen.dart';
import 'package:llggflutter_app/Screens/Welcome/components/background.dart';
import 'package:llggflutter_app/components/round_button.dart';
import 'package:llggflutter_app/constants.dart';
import 'package:flutter_screenutil/screenutil.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 To SQD",
style: TextStyle(fontWeight: FontWeight.bold),
),
SizedBox(height: size.height * 0.1),
//Image.asset('images/SQDlogo.png'),
//-SvgPicture.assets("assetsName")
RoundeButton(
text: "LOGIN",
press: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return LoginScreen();
},
),
);
},
),
RoundeButton(
text: "SIGN UP",
color: kPrimaryLightColor,
textColor: Colors.black,
press: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return LoginScreen();
},
),
);
},
),
],
),
);
}
}
- welcome下的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(
children: <Widget>[
Positioned(
top: 80,
left: 130,
child: Image.asset("lip/Screens/Images/top.png"),
/*Image.network(
'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3196884667,4151300997&fm=26&gp=0.jpg',
width: size.width * 0.3,
),*/
),
/* Positioned(
bottom: 0,
left: 0,
child: Image.network(
'https://images.pexels.com/photos/2127969/pexels-photo-2127969.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
width: size.width * 0.3,
),
),*/
child,
],
),
);
}
}
6.signup_screen.dart
import 'package:flutter/material.dart';
class SignUpScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Body(),
);
}
}
class Body extends StatelessWidget {
@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: 80,
left: 35,
child: Image.network(
'http://cdn.cnbj1.fds.api.mi-img.com/mi-mall/b72c3b4d58f15c2f2053f11510e72116.jpg?w=800&h=532',
width: size.width * 0.8,
),
)
],
),
);
}
}
- login_screen.dart
import 'package:flutter/material.dart';
import 'package:llggflutter_app/Screens/Login/components/body.dart';
class LoginScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Body(),
);
}
}
- Login文件下的body.dart
import 'package:flutter/material.dart';
import 'package:llggflutter_app/Screens/Login/components/background.dart';
import 'package:llggflutter_app/Screens/Signup/signup_screen.dart';
import 'package:llggflutter_app/components/already_have_an_account_acheck.dart';
import 'package:llggflutter_app/components/round_button.dart';
import 'package:llggflutter_app/components/round_input_field.dart';
import 'package:llggflutter_app/components/round_password_field.dart';
import 'package:llggflutter_app/components/text_field_container.dart';
import 'package:llggflutter_app/constants.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(
SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
/* Text(
"WELCOME LOGIN",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.grey,
fontWeight: FontWeight.bold,
),
),*/
SizedBox(height: size.height * 0.3),
RoundedInputField(
hintText: "Your Email ",
onChanged: (value) {
},
),
RoundedPassworldField(
onChanged: (value) {
},
),
RoundeButton(
text: "LOGIN",
// color: kPrimaryLightColor,
// textColor: Colors.black,
press: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return SignUpScreen();
},
),
);
},
),
// SizedBox(height: size.height * 0.1),
AlreadyHaveAnAccountCheck(
press: () {
},
),
SizedBox(height: size.height * 0.04),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
border: Border.all(),
shape: BoxShape.circle,
),
child: Image.network(
'https://src.onlinedown.net/d/file/p/2019-08-06/2dc4d1b597725835d85259829db3fcff.jpg',
width: size.width * 0.1),
)
],
)
],
),
);
}
}
9.login文件下的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 Scaffold(
body: Container(
width: double.infinity,
height: size.height,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Positioned(
top: 0,
left: 50,
child: Image.network(
'http://www.smu-sqd.com/upload/img/201912120939063520.png',
width: size.width * 0.55,
height: size.height * 0.3,
)
xxxxx
//"assets/images/SQDlogo.png",
),
//child,
],
),
),
);
}
}
10.already_have_an_account_acheck.dart
import 'package:flutter/material.dart';
import 'package:llggflutter_app/constants.dart';
class AlreadyHaveAnAccountCheck extends StatelessWidget {
final bool login;
final Function press;
const AlreadyHaveAnAccountCheck({
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,
),
),
)
],
);
}
// This widget is the root of your application.
}
11.round_button.dart
import 'package:flutter/material.dart';
import 'package:llggflutter_app/constants.dart';
class RoundeButton extends StatelessWidget {
final String text;
final Function press;
final Color color, textColor;
const RoundeButton({
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, horizontal: 50), //调节间距
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),
),
),
),
);
}
}
12.round_input_field.dart
import 'package:flutter/material.dart';
import 'package:llggflutter_app/components/text_field_container.dart';
import 'package:llggflutter_app/constants.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,
Color color,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return TextFieldContainer(
child: TextField(
onChanged: onChanged,
decoration: InputDecoration(
fillColor: Colors.black,
icon: Icon(
icon,
color: Colors.blue,
),
hintText: hintText,
border: InputBorder.none),
),
);
}
}
13.round_password_field.dart
import 'package:flutter/material.dart';
import 'package:llggflutter_app/components/text_field_container.dart';
import 'package:llggflutter_app/constants.dart';
class RoundedPassworldField extends StatelessWidget {
final ValueChanged<String> onChanged;
const RoundedPassworldField({
Key key,
this.onChanged,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return TextFieldContainer(
child: TextField(
obscureText: true,
onChanged: onChanged,
decoration: InputDecoration(
fillColor: Colors.red, //*** */
hintText: "Password",
icon: Icon(
Icons.lock,
color: Colors.blue,
),
suffixIcon: Icon(
Icons.visibility,
color: Colors.blue,
),
border: InputBorder.none,
),
),
);
}
}
14.text_field_container.dart
import 'package:flutter/material.dart';
import 'package:llggflutter_app/constants.dart';
class TextFieldContainer extends StatelessWidget {
final Widget child;
const TextFieldContainer({
Key key,
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: Colors.grey,
borderRadius: BorderRadius.circular(29),
),
child: child,
);
}
}
a。ok,全部代码完毕,程序里的Image.network 后面的地址,大家换成自己的哈;
b。输入框中的安全线一样的东西是个bug:
大家可以将输入框与键盘隔开写距离,然后这个安全线会消失,或者使用SingleChildScrollView(),将排布的内容放进去,也会避免这个问题(这时候把background里的东西放到body中,要不然SingleChildScrollView()无法对图片进行排布)
c。下方的微信图标是画上去的,并没有引用,做做样子哈
关于第三方登录的实现有个github上的sharesdk包,大家可以找下哈。
添加链接描述
喜欢的朋友可以收藏或点个赞哈,或留言交流。大家一起学习呀。