Flutter Widget 靜態佈局實戰

前面兩篇文章介紹了 Flutter win環境的安裝,以及利用listview 實現了簡單佈局。(這篇文章篇幅有點長,讀完大概須要8.88分鐘)html

Flutter 入門實現 ListView 列表頁面以及收藏頁面git

Flutter 環境搭建以及填坑指南(Win10 系統且已有 Android 開發環境 github

這篇文章主要介紹如下內容:bash

1. ListView 能實現什麼效果?網絡

2. widget 如何添加到 ListView 中?app

3. ListView 點擊事件,單個 widget 點擊事件框架

4. ( 重點 ) widget 如何垂直、水平擺放?less

5. 圖片、Icon、Text widget 的簡單使用dom

在這篇文章Flutter 入門實現 ListView 列表頁面以及收藏頁面中雖然實現了一個列表,可是怎麼實現的還沒仔細研究,如今就先從研究 ListView的實現開始吧。ide

先看一下以前實現的效果:

ListView 列表
實現的代碼主要是 RandomWordsState類中的下面代碼:

return new ListTile(
      // 單詞佈局
      title: new Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
      // 喜歡當心心佈局
      trailing: new Icon(
        alreadySaved ? Icons.favorite : Icons.favorite_border,
        color: alreadySaved ? Colors.red : null,
      ),
      // ListView item 的點擊事件
      onTap: () {
        // 通知框架狀態已經改變
        setState(() {
          if (alreadySaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
      },
    );
複製代碼

從上面的代碼中能夠看出實現這個列表主要就是操做了 ListTile 這個 Widget,那麼咱們看看這個ListTile的構造方法都提供了上面功能吧!註釋都寫在代碼中了~

/// Requires one of its ancestors to be a [Material] widget.
  const ListTile({
    Key key,
    // 在列表的左邊添加的 widget(如文末圖中的左邊圖片)
    this.leading,
    // 標題
    this.title,
    // 副標題
    this.subtitle,
    // 在列表的右邊添加的 widget(如文末圖中的右邊心形 icon)
    this.trailing,
    // 若是 isThreeLine 爲 true, subtitle 則不能爲 null,默認爲 false
    // 若是 副標題爲空則列表平鋪一行顯示,若是 副標題 不爲空,則副標題所佔的佈局是兩行
    // 若是 isThreeLine = true 則副標題能夠顯示三行。
    this.isThreeLine = false,
    // bool 類型,默認爲false ,若是爲 true 則 ListTile 在垂直方向是密集型擺放
    //(具體效果待後面去實現,這裏只是看了註釋後的理解)
    this.dense,
    // 內容的邊距
    this.contentPadding,
    // item 是否能點擊
    this.enabled = true,
    // item 的點擊事件
    this.onTap,
    // item 的長按事件
    this.onLongPress,
    // item 是否選中標記
    this.selected = false,
  }) 
複製代碼

flutter 的開發語言是dart,這個語言以前沒學過,這裏就先不深刻學習了,網上有比較好的這個博主 戀貓月亮 寫的系列的文章寫的很好。我這裏就只寫實現上面圖片中展現的效果。

1. ListView 能實現什麼效果?

ListView 不只能夠實現列表佈局,還能夠實現 Android 中的 ScrollView 的功能。關於 滾動的 widget 還有其餘的實現,可參考**可滾動Widget簡介**

實現列表功能,若是是符合ListTile的樣式,直接使用ListTile實現很方便。(目前還沒學到如何實現多佈局,後面學習再寫一篇)

實現ScrollView功能,直接在build方法的body中添加咱們的 widget。僞代碼以下:

定義了一個DetailScreen詳情頁面,繼承了StatelessWidget,在build方法中返回了頁面的內容:appBar 是標題欄,body 是顯示的內容

class DetailScreen extends StatelessWidget {
 // Declare a field that holds the pair
 final WordPair pair;

 // In the constructor, require a pair
 DetailScreen({Key key, @required this.pair}) : super(key: key);

 @override
 Widget build(BuildContext context) {
 return new Scaffold(
      appBar: new AppBar(
        // 接收傳遞過來的單詞作標題名字
        title: new Text("${pair.asPascalCase}"),
      ),
      // 使用 ListView 作滾動列表
      body: new ListView(  
        children: [
          // 顯示網絡圖片
          new Image.asset(
            'images/wali.jpg',
            width: 600.0,
            height: 240.0,
            fit: BoxFit.cover,
          ),
          // 標題行(文末有實現效果)
          titleSection,
          // 按鈕行(文末有實現效果)
          buttonSection,
          // 描述文本(文末有實現效果)
          textSection,
        ],
      ),
    );
  }
}
複製代碼

2. widget 如何添加到 ListView 中?

上面的僞代碼中在構建一個有狀態的widget的時候會重寫 build方法,在該方法中的 body返回咱們實現的 widget便可。

3. ListView 點擊事件,單個 widget 點擊事件

若是ListView使用ListTile實現列表的話,直接使用ListTile中的 onTap實現列表點擊效果。若是不是用ListTile實現,那就使用單個widget的點擊事件吧。

widget的若是有onTap方法能夠直接調用該方法便可實現,若是沒有該方法,則須要使用GestureDetector來實現點擊效果,例如上圖中的心形喜歡點擊事件,僞代碼實現以下:

關於GestureDetector可參考該文章 手勢識別GestureDetector

trailing: new GestureDetector(
        // 心形喜歡 icon
        child: new Icon(
          alreadySaved ? Icons.favorite : Icons.favorite_border,
          color: alreadySaved ? Colors.red : null,
        ),
        // 點擊事件
        onTap: (){
          // 通知框架狀態已經改變
          setState(() {
            if (alreadySaved) {
              _saved.remove(pair);
            } else {
              _saved.add(pair);
            }
          });
        },
      ),
複製代碼

4. widget 如何垂直、水平擺放?

最多見的佈局模式之一是垂直或水平排列widget。在Flutter可使用行Row水平排列widget,並使用列Column垂直排列widget。 同時,每一個孩子自己能夠是一個Row或一個Column,依此類推。如下示例顯示如何在行或列內嵌套行或列。

經過下面兩張圖片能夠學到在實現佈局時如何拆分: 參考連接 widget 佈局

左側的一列和右側的圖片
左側的Column widget樹嵌套行和列

在控制行或列對齊其子項時使用mainAxisAlignment( 主軸 ) 和crossAxisAlignment( 橫軸 ) 屬性來。 對於行(Row)來講,**主軸是水平方向,橫軸垂直方向。**對於列(Column)來講,主軸垂直方向,橫軸水平方向。

Row
Column
MainAxisAlignmentCrossAxisAlignment 類提供了不少控制對齊的常量. MainAxisAlignment

  • center → const MainAxisAlignment :子 widget在主軸方向上居中顯示

  • end → const MainAxisAlignment :子 widget在主軸方向上居右邊顯示,若是是水平方向,那麼由 TextDirection 來決定end是在左邊(ltr)仍是在右邊(rtl)。若是是豎直方向,那麼由 VerticalDirection 來決定end是在上邊(up)仍是在下邊(down)

  • start → const MainAxisAlignment:子 widget在主軸方向上居左邊顯示,同理 end

  • spaceAround → const MainAxisAlignment:子widget中的第一個和最後一個widget距離邊的距離是它與中間的距離的一半。(這裏比較抽象,後期實現效果了會順帶講解)

  • spaceBetween → const MainAxisAlignment:子widget中的第一個和最後一個貼邊,剩餘的子widget將中間的空間平分。

  • spaceEvenly → const MainAxisAlignment:子widget 將佈局空間徹底平分

    Row 方向徹底平分

  • values → const List<MainAxisAlignment>:根據值得大小來分配空間,值越大空間分配越多。

CrossAxisAlignment 屬性相同的基本和上面介紹的同樣,就不贅述了。

Expanded widget

Expanded widget,能夠將widget的大小設置爲適和行或列 Expanded有個屬性flex(彈性係數),默認狀況下,每一個widget的彈性係數爲1,也就是會鋪滿布局。

例如實現:三張圖片水平鋪滿屏幕,便可使用Expanded包裹Image而後設置flex:1,不設置也行,由於默認flex就是1

效果圖

僞代碼以下:

body: new Center(
  child: new Row(
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [
      new Expanded(
        child: new Image.asset('images/pic1.jpg'),
      ),
      new Expanded(
        child: new Image.asset('images/pic2.jpg'),
      ),
      new Expanded(
        child: new Image.asset('images/pic3.jpg'),
      ),
複製代碼

彙集 widgets

默認狀況下,行或列沿着其主軸會盡量佔用儘量多的空間,但若是要將孩子緊密彙集在一塊兒,能夠將mainAxisSize設置爲MainAxisSize.min

例如實現:五個星形圖標圖標緊湊在一塊兒。

效果圖
僞代碼以下:

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    var packedRow = new Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        new Icon(Icons.star, color: Colors.green[500]),
        new Icon(Icons.star, color: Colors.green[500]),
        new Icon(Icons.star, color: Colors.green[500]),
        new Icon(Icons.star, color: Colors.black),
        new Icon(Icons.star, color: Colors.black),
      ],
    );

  // ...
}
複製代碼

5. 圖片、Icon、Text widget 的簡單使用

這些都是基礎控件使用起來很簡單的,可查看這個文檔介紹:基礎 Widget

在學習完上面的內容咱們能夠實現出目前的樣式了:

flutter_1.gif

實現列表功能,以及一個可滾動的詳情頁面,頂部的標題是 listview 傳遞過去的單詞。

文章篇幅過長了,這裏就不介紹上圖的實現過程了,源碼地址以下 以爲還湊合的給個star,好讓我繼續堅持寫下去~ 源碼地址

看源碼或者上文中不理解的能夠聯繫我,我會知無不言的。

本文完。

相關文章
相關標籤/搜索