demo传送门git
先看下闪屏动画的代码:github
import 'package:flutter/material.dart';
import 'login_screen.dart';
class SplashScreen extends StatefulWidget {
@override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: Duration(milliseconds: 3000));
_animation = Tween(begin: 0.0, end: 1.0).animate(_controller);
/* 动画事件监听器
监听动画的执行状态,这里监听动画结束的状态,若是结束则执行页面跳转
*/
_animation.addStatusListener((status){
if (status == AnimationStatus.completed) {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => LoginView()),
(route) => route==null
);
}
});
// 播放动画
_controller.forward();
}
@override
Widget build(BuildContext context) {
return FadeTransition( // 透明动画组件
opacity: _animation, // 执行动画
child: Image.network(
'http://img.ph.126.net/L-kWzHFAymXFUvgauDtB-g==/2596888135149416738.jpg',
scale: 2.0, // 缩放
fit: BoxFit.cover, // 充满容器
),
);
}
}
复制代码
AnimationContrller
是Animation
的一个子类,能够用它来控制动画,好比执行时间。 设置好动画,就设置一个动画事件的监听器animation.addStatusListener
,它能够监听到动画的执行状态,这里监听到动画结束,执行页面跳转动做。bash
关于图片的设置,以及路由的跳转,在后面都有详细的解释。网络
这是一个很简单的登陆界面,先看下页面里主要都有什么。闭包
这边了解过Flutter的小伙伴们,看到了这个布局一会儿就可以想获得Column
,下面看主体代码app
import 'package:flutter/material.dart';
import 'home_page.dart';
class LoginView extends StatefulWidget {
@override
_LoginViewState createState() => _LoginViewState();
}
class _LoginViewState extends State<LoginView> {
var _photoController = TextEditingController();
var _passController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: Image.asset('images/logo.jpg'),
),
AccountTextField(),
PasswordTextField(),
LoginButton(),
],
),
),
);
}
// 帐号TextField
Widget AccountTextField() {
return Padding(
padding: const EdgeInsets.fromLTRB(15.0, 30.0, 15.0, 0.0),
child: TextField(
controller: _photoController,
onChanged: (text) { // 内容变化
print('输入了$text');
},
decoration: InputDecoration(
prefixIcon: Icon(Icons.phone_iphone),
fillColor: Colors.white70,
filled: true,
labelText: '请输入手机号'
),
)
);
}
// 密码TextField
Widget PasswordTextField() {
return Padding(
padding: const EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 0.0),
child: TextField(
controller: _passController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.email),
fillColor: Colors.white70,
filled: true,
labelText: '请输入密码'
),
obscureText: true,
)
);
}
// 登陆按钮
Widget LoginButton() {
return GestureDetector(
child: Container(
margin: const EdgeInsets.fromLTRB(0.0, 30.0, 0.0, 0.0),
width: MediaQuery.of(context).size.width - 30.0,
height: 50.0,
child: Card(
color: Colors.lightBlue,
elevation: 6.0,
child: Center(
child: Text('登陆', style: TextStyle(fontSize: 18.0, color: Colors.white)),
)
)
),
onTap: (){
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => HomePage()),
(route) => route==null
);
},
);
}
}
复制代码
说明一下布局:less
Column Widget
Widget
是一个logo图片,它被Padding Widget
包裹着,咱们能够经过Padding
的padding
属性,轻松的控制这个Widget
位置和边距子Widget
是一个TextField Widget
,和上面的图片同样,经过Padding Widget
包裹着,很容易控制它们的边距Widget
用的是一个Container
,而后里面经过GestureDetector
添加了点击事件,其实这里的登陆按钮,彻底能够经过button性质的Widget
来作,这里只是想记录一下,给控件添加手势的功能下面简单介绍一下几个简单的Widget
:iphone
本地图片经过 pubspec.yaml
文件(位于项目根目录),来识别应用程序所用的图片ide
在根目录下新建一个images文件夹,存放图片使用函数
assets:
- images/logo.png
- images/background.png
复制代码
代码中能够直接引用,和iOS开发中的使用相似:Image.asset('images/logo.jpg')
网络图片的加载,看一下加载网络图片的方法Image.network('图片连接')
,也很简单。
最简单的输入框TextField()
,只要这一句话,输入框其实就有了
经过项目里的代码能够看到,TextField
里有个controller
属性,经过这个来获取TextField
的值:controller.text
。
作iOS的小伙伴们都知道iOS中的TextField
属性中有个placeholder
属性,那么这里能够经过decoration
里的labelText
设置这个值。
通常的密码输入框,咱们都是隐式显示,也就是▪️▪️▪️▪️来表示。obscureTexts
设置为true
便可。
还能够在左侧添加一个icon,代码中也能够看到用法。
有兴趣的小伙伴能够经过源码里的属性值,来了解这个Widget
。
本人项目中使用了不少圆角矩形的边框,这里有点坑,下面看下代码:
import 'package:flutter/material.dart';
class TextFieldView extends StatelessWidget {
Widget borderTextField() {
return TextField(
decoration: InputDecoration(
contentPadding: EdgeInsets.all(15.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(color: Colors.red, width: 10.0, style: BorderStyle.solid)
)
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('TextField')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: borderTextField(),
),
),
);
}
}
复制代码
效果图:
可能,细心的小伙伴们已经发现了问题
borderSide: BorderSide(color: Colors.red, width: 10.0, style: BorderStyle.solid)
,这句代码对边框的设置毫无做用,这里的输入框,并非咱们想要的
好在坑已被前人填满,:边框颜色解决方案
因此正确的代码姿式应该是:
Widget borderTextField() {
return Theme(
data: ThemeData(primaryColor: Colors.red, hintColor: Colors.blue),
child: TextField(
decoration: InputDecoration(
contentPadding: EdgeInsets.all(15.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
// 下面方法无效
// borderSide: BorderSide(color: Colors.red, width: 10.0, style: BorderStyle.solid)
)
),
),
);
}
复制代码
效果图:
再者就是边框的粗细改变,暂时没有找到合适的方法,可是能够经过重构的方式,请看代码:
import 'package:flutter/material.dart';
class TextFieldView extends StatelessWidget {
Widget borderTextField() {
return Container(
padding: const EdgeInsets.all(5.0),
height: 40.0,
decoration: BoxDecoration(
color: Colors.white70,
border: Border.all(color: Colors.yellow, width: 5.0),
borderRadius: BorderRadius.circular(8.0)
),
child: TextFormField(
decoration: InputDecoration.collapsed(hintText: '请输入内容'),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('TextField')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: borderTextField(),
),
),
);
}
}
复制代码
效果图:
Navigator
继承StatefulWidget
,它也是小组件,有不少相关静态函数,能够帮助咱们达到页面跳转和数据交互的功能:
使用Navigator.push实现发送路由,Navigator.pop返回上一个页面。
push
函数的有两个:上下文context、Route
。这里使用的是MaterialPageRoute
,该类必需要传入一个闭包函数WidgetBuilder
,参数是 BuildContext对象
,咱们使用的是匿名函数的形式,加上箭头符号:builder: (context) => HomePage()