3.flutter開發(fā)基礎(chǔ)-Widget組件

1.Widge組件分類

在flutter中,所有UI元素都是widget組件,除了我們常見的button,Image這些可見元素,布局也是組件,甚至文本格式控制也是組件。這里我們先簡單講解一下我們通常概念的上的UI控件。在flutter中組件有兩種:有狀態(tài)組件和無狀態(tài)組件。

  • 無狀態(tài)組件(stateless widget),無狀態(tài)組件不提供可變狀態(tài)維護(hù),無狀態(tài)組件僅根據(jù)其屬性來渲染,
  • 有狀態(tài)組件(stateful Widget),組件自己維護(hù)狀態(tài),組件渲染由SetState方法調(diào)用,更具state的變化差異來更新渲染。所有的stateful widget都是建立在stateless widget上的。
    這里我們先講解stateless widget, flutter中的stateless widget主要分為這幾類:
  • Visual Base Elemet, 可視基礎(chǔ)元素比如:Text,Image, Icon
  • Layout: 布局元素,flutter比較特別一點(diǎn),它把布局也作為頁面元素,這樣做的主要目的是可以簡化布局計(jì)算。以前UI做Layout通常通過Layout引擎根據(jù)預(yù)定的約束來進(jìn)行計(jì)算, 計(jì)算過程實(shí)際上是做多元方程式求解,元素越多求解計(jì)算就越慢,參考:從 Auto Layout 的布局算法談性能
    。而flutter將layout也作為頁面元素,使得布局在局部范圍就可以求解。Layout元素有:Row,Column,Center,Align,Padding等
  • Painting and Effect Widgets& Animation and Motion
    ,繪制和效果組件。繪制和效果組件主要是負(fù)責(zé)可視元素的裝飾效果,比如實(shí)現(xiàn)邊框(DecoratedBox),實(shí)現(xiàn)半透明(Opacity),位移旋轉(zhuǎn)變換(Transform),Animation and Motion是比較特殊的效果組件,用于實(shí)現(xiàn)動(dòng)畫效果
  • Container&compound element 大多數(shù)我們常用的各種控件都是由基礎(chǔ)元素和布局組合而成的,比如button由Text,Image,DecoratedBox等元素組成
  • Interaction Model Widgets, 這個(gè)是專門處理事件響應(yīng)的組件,用于響應(yīng)用戶的操作

2.讓我們來創(chuàng)建Hello World

首先我們先來寫一個(gè)最基本的flutter應(yīng)用吧。

1.在適當(dāng)?shù)哪夸泩?zhí)行:

flutter init -o my_hello_world_app

2.替換my_hello_world_app/lib/main.dart文件中的內(nèi)容:

import 'package:flutter/material.dart';
void main() => runApp(new Center(child: new Text('Hello, world!')));

3.在my_hello_world_app目錄下執(zhí)行:

flutter start

4.你將會(huì)在手機(jī)上看到:


這里寫圖片描述

如果你能一切順利的來到這里,那么恭喜你,你已經(jīng)成功使用flutter開發(fā)了一個(gè)android的應(yīng)用,雖然這個(gè)應(yīng)用看上去比較單一。

main方法是這個(gè)應(yīng)用的入口,要運(yùn)行一個(gè)應(yīng)用的話需要使用runApp方法,它接收一個(gè)Widget控件作為參數(shù),并且把這個(gè)控件作為控件樹的根節(jié)點(diǎn)。在我們這個(gè)例子里,控件樹里有兩個(gè)控件,Center控件和它的子節(jié)點(diǎn)Text。通常情況下框架會(huì)強(qiáng)制將根控件充滿整個(gè)屏幕,所以相對的Text控件就以屏幕為中心了。

重要概念:
在編寫flutter應(yīng)用的時(shí)候,通常情況下需要自定義組件,這些組件繼承自StatelessComponentStatefulComponent,選擇要繼承哪一個(gè)取決于這個(gè)組件是否需要管理狀態(tài)和配置。一個(gè)組件的主要工作就是實(shí)現(xiàn)build方法,這個(gè)方法用來反應(yīng)該組件在其他組件中的表現(xiàn)形式。最后底層框架會(huì)統(tǒng)一從上到下調(diào)用build方法直至渲染樹的最底層。

基本控件

flutter提供了一套完備的基本控件,最常用的有如下幾個(gè):

  • Text :Text提供了一個(gè)用來顯示文本的一次性控件(即無狀態(tài))。
  • Row, Column:這兩個(gè)控件用來顯示水平或垂直方向上的多個(gè)組件,并且是可伸縮的。
  • Stack:可以將多個(gè)組件以一定的順序排列,可以使用Positioned控件來指定組件在Stack中的順序。
  • Container: 是一個(gè)可視化的矩形控件,它可以使用BoxDecoration來進(jìn)行外觀裝飾,裝飾內(nèi)容可以是背景,邊框和陰影等。Container也有外邊距,內(nèi)邊距等屬性,也可以約束自身的大小,另外值得一提的是Container還可以利用矩陣在三維控件內(nèi)做轉(zhuǎn)換。

下面結(jié)合一些基本的控件來自定義我們的組件并構(gòu)建應(yīng)用:
修改main.dart代碼如下

import 'package:flutter/material.dart';

class MyToolBar extends StatelessComponent { //(3)
  MyToolBar({ this.title });

  final Widget title; //(6)

  Widget build(BuildContext context) {
    return new Container(
      height: 56.0,
      padding: const EdgeDims.symmetric(horizontal: 8.0),
      decoration: new BoxDecoration(
        backgroundColor: Colors.blue[500]
      ),
      child: new Row([
        new IconButton(icon: 'navigation/menu'),
        new Flexible(child: title),
        new IconButton(icon: 'action/search'),
      ])
    );
  }
}

class MyScaffold extends StatelessComponent { //(4)
  Widget build(BuildContext context) {
    return new Material(
      child: new Column([
        new MyToolBar(
          title: new Text('Example title', style: Typography.white.title)
        ),
        new Flexible(
          child: new Center(
            child: new Text('Hello, world!')
          )
        )
      ])
    );
  }
}

void main() {
  runApp(new MaterialApp( //(1)
    title: 'My app',
    routes: <String, RouteBuilder>{ //(2)
      '/': (RouteArguments args) => new MyScaffold() //(5)
    }
  ));
}

同時(shí)確保flutter.yaml文件內(nèi)容如下:

name: my_app
material-design-icons:
  - name: action/search
  - name: navigation/menu

我們先來運(yùn)行一下這個(gè)應(yīng)用:


這里寫圖片描述

恭喜你,順利存活。
代碼解釋如下:

  • (1)處的MaterialApp是整個(gè)應(yīng)用的主題控件,一般我們自定義的組件要寫在它里面才會(huì)有Material的主題風(fēng)格
  • (2)處的routes的作用是頁面導(dǎo)航作用,/表示應(yīng)用打開的第一個(gè)頁面。
  • (3)處的MyToolBar是我們自定義的一個(gè)無狀態(tài)組件,通過build方法,我們可以看出其最外層是一個(gè)Container控件,控件高為56dp,左右內(nèi)邊距8dp,它由一個(gè)BoxDecoration做修飾,修飾內(nèi)容是將背景顏色改為Colors.blue[500]這種顏色。Container的內(nèi)部是一個(gè)Row,Row的兩端分別是一個(gè)圖標(biāo)按鈕,中間是另一個(gè)控件Flexible,它的作用是填充掉Row的剩余部分。在Flexible中傳入的是title這個(gè)內(nèi)部字段。
  • (4)處的MyScaffold組件將其子節(jié)點(diǎn)用垂直的方式組織起來,在Column的第一個(gè)位置是我們自定義的MyToolBar,在構(gòu)造MyToolBar的時(shí)候?qū)⒁粋€(gè)Text控件作為它的命名可選參數(shù)title的值傳遞進(jìn)去。在Column的第二個(gè)位置是一個(gè)Flexible用來填充剩余的空間,在Flexible里面放置了一個(gè)Center組件,Center組件里則是一個(gè)Text用來顯示“Hello,World”。
  • (5)處表示這個(gè)應(yīng)用的第一個(gè)見面就是MyScaffold

這種flutter這種層層包裹的感覺就是前面提到的組件外構(gòu)建UI一小部分含義,眼尖的同學(xué)可能已經(jīng)看到(6)處的title使用的是final修飾符,這里要說明一下繼承自StatelessComponent的組件,如內(nèi)部有配置,屬性或狀態(tài)的統(tǒng)一需要使用final修飾符,表示這個(gè)組件本身自己是無狀態(tài)的,需要依賴它外部的其他組件。這也是'組件外構(gòu)建UI'最重要的含義所在

Material應(yīng)用

上面那個(gè)應(yīng)用我們使用自己的組件進(jìn)行應(yīng)用開發(fā),發(fā)現(xiàn)應(yīng)用整體美觀度不高。是因?yàn)閒lutter中應(yīng)用界面會(huì)撐滿整個(gè)屏幕,所以有一部分內(nèi)容可能會(huì)被狀態(tài)欄擋住。其實(shí)flutter提供了一系列的控件供開發(fā)人員開發(fā)Material風(fēng)格的應(yīng)用,這之中就有MaterialAppScaffoldToolBarFloatingActionButton等。下面看一個(gè)使用了這些控件的例子:

修改main.dart內(nèi)容如下:

import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(
      title: 'Flutter Tutorial',
      routes: {'/': (RouteArguments args) => new TutorialHome()}));
}

class TutorialHome extends StatelessComponent {
  Widget build(BuildContext context) {
    return new Scaffold(
        toolBar: new ToolBar(
            left: new IconButton(icon: 'navigation/menu'),
            center: new Text('Example title'),
            right: [new IconButton(icon: 'action/search')]),
        body: new Center(child: new Text('Hello, world!')),
        floatingActionButton:
            new FloatingActionButton(child: new Icon(icon: 'content/add')));
  }
}

修改flutter.yaml文件內(nèi)容如下:

name: my_app
material-design-icons:
  - name: action/search
  - name: content/add
  - name: navigation/menu

運(yùn)行結(jié)果如下:


這里寫圖片描述

現(xiàn)在我們的應(yīng)用看起來是不是更像是一個(gè)Material Design的應(yīng)用了?我們使用的ScaffoldToolBar讓ToolBar自帶了陰影并且字體風(fēng)格有有了調(diào)整。另外還加上了FloatingActionButton

總結(jié)

本文主要講解flutter中的組件分類,對如何創(chuàng)建簡單Stateless組件進(jìn)行了演示

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,117評(píng)論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,860評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,128評(píng)論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,291評(píng)論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,025評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,421評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,477評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,642評(píng)論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,177評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,970評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,157評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,717評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,410評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,821評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,053評(píng)論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,896評(píng)論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,157評(píng)論 2 375

推薦閱讀更多精彩內(nèi)容

  • 以下內(nèi)容基本翻譯自A Tour of the Flutter Widget Framework,翻譯的可能并不完全...
    INeil閱讀 10,280評(píng)論 0 4
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,682評(píng)論 25 708
  • 2017年11月5號(hào) 星期天 天氣晴 每次回老家我都幫婆婆打掃衛(wèi)生,料理家務(wù)忙的不可開交,孩子們玩的不亦樂乎! 中...
    松鴿閱讀 140評(píng)論 0 0
  • 11 攙起芹子的是小英。 冬冬,也早放了自己的白菜,跳到溝渠下面,把那塊爛白菜舉了上來。人,也爬了出來,站在她倆身...
    筱昀閱讀 581評(píng)論 21 27
  • 說的話像個(gè)大啞巴,一口一個(gè)爪牙 沒有人說的話,是一個(gè)大啞巴 我是一個(gè)啞巴 能說話的啞巴 能漏出牙齒的啞巴 我不說話...
    導(dǎo)演張升志閱讀 476評(píng)論 0 0