筆記-Flutter應用啓動閃屏到登陸界面

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,  // 充滿容器
      ),
    );
  }
}

複製代碼

AnimationContrllerAnimation的一個子類,能夠用它來控制動畫,好比執行時間。 設置好動畫,就設置一個動畫事件的監聽器animation.addStatusListener,它能夠監聽到動畫的執行狀態,這裏監聽到動畫結束,執行頁面跳轉動做。bash

關於圖片的設置,以及路由的跳轉,在後面都有詳細的解釋。網絡

登陸界面

這是一個很簡單的登陸界面,先看下頁面裏主要都有什麼。閉包

  • 圖片logo
  • 上下兩個輸入框
  • 一個登陸按鈕

這邊瞭解過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包裹着,咱們能夠經過Paddingpadding屬性,輕鬆的控制這個Widget位置和邊距
  • 第二個和第三個子Widget是一個TextField Widget,和上面的圖片同樣,經過Padding Widget包裹着,很容易控制它們的邊距
  • 第四個子Widget用的是一個Container,而後裏面經過GestureDetector添加了點擊事件,其實這裏的登陸按鈕,徹底能夠經過button性質的Widget來作,這裏只是想記錄一下,給控件添加手勢的功能

下面簡單介紹一下幾個簡單的Widgetiphone

圖片Widget

本地圖片經過 pubspec.yaml 文件(位於項目根目錄),來識別應用程序所用的圖片ide

在根目錄下新建一個images文件夾,存放圖片使用函數

assets:
    - images/logo.png
    - images/background.png
複製代碼

代碼中能夠直接引用,和iOS開發中的使用相似:Image.asset('images/logo.jpg')

網絡圖片的加載,看一下加載網絡圖片的方法Image.network('圖片連接'),也很簡單。

TextField Widget

最簡單的輸入框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

Navigator繼承StatefulWidget,它也是小組件,有不少相關靜態函數,能夠幫助咱們達到頁面跳轉和數據交互的功能:

  • push 將設置的route信息推送到Navigator上,實現頁面跳轉
  • of 主要是獲取Navigator最近實力的好狀態
  • pop 返回到上個頁面
  • canPop 判斷是否能夠導航到新頁面
  • popAndPushNamed 指定一個路由路徑,並導航到新頁面
  • popUntil 反覆執行pop知道該函數的參數predicate返回true爲止
  • pushAndRemoveUntil 將給定路由推送到Navigator,刪除先前的路由,直到該函數的參數predicate返回true爲止
  • pushNamed 將命名路由推送到Navigator
  • pushNamedAndRemoveUntil 將命名路由推送到Navigator,刪除先前的路由,直到該函數的參數predicate返回true爲止。
  • pushReplacement 路由替換。
  • pushReplacementNamed 這個也是替換路由操做。推送一個命名路由到Navigator,新路由完成動畫以後處理上一個路由。
  • removeRoute 從Navigator中刪除路由,同時執行Route.dispose操做。
  • removeRouteBelow 從Navigator中刪除路由,同時執行Route.dispose操做,要替換的路由是傳入參數anchorRoute裏面的路由。
  • replace 將Navigator中的路由替換成一個新路由。
  • replaceRouteBelow 將Navigator中的路由替換成一個新路由,要替換的路由是是傳入參數anchorRoute裏面的路由。

路由的操做方式

使用Navigator.push實現發送路由,Navigator.pop返回上一個頁面。

push函數的有兩個:上下文context、Route。這裏使用的是MaterialPageRoute,該類必需要傳入一個閉包函數WidgetBuilder,參數是 BuildContext對象,咱們使用的是匿名函數的形式,加上箭頭符號:builder: (context) => HomePage()

相關文章
相關標籤/搜索