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()