谷歌移動UI框架Flutter教程之Widget

      網(wǎng)友投稿 827 2022-05-30

      引言

      在之間我已經(jīng)介紹了關(guān)于Flutter的下載安裝以及配置,還有開發(fā)工具Android Studio的配置,還不知道的同學(xué)可以看看我這篇博客——谷歌移動UI框架Flutter入門。這里為什么非要用Android Studio,我可以解釋一下。Android Studio是Google的親兒子,由谷歌一手開發(fā),而Flutter也是谷歌推出的技術(shù),所以在支持和兼容問題上,Android Studio是非常有優(yōu)勢的。老話說得好,肥水不流外人田,谷歌內(nèi)部肯定是將Android Studio對Flutter的優(yōu)化做到最佳的。

      Widget基本組件

      那么話不多說,我們先來熟悉一下關(guān)于Flutter的Widget組件,在Flutter中,一切皆組件,TextView、Image、Row、Column等等,都統(tǒng)稱組件。

      首先,我們就來了解一下文本組件(Text)。學(xué)過前端的同學(xué)對UI部分應(yīng)該都很了解,那Flutter當(dāng)然也沒有什么特別的,無非也就是文本內(nèi)容、大小、字體樣式、顏色等等的設(shè)置,那么首先我們就先來編寫一個案例。找到lib目錄下的main.dart,我們將在這個文件中編寫代碼。

      import 'package:flutter/material.dart'; void main() { runApp(MyTextApp()); } /** * 文本組件(Text)的使用 */ class MyTextApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Text Demo', home: Scaffold( appBar: AppBar(title: Text('文本控件的使用'),), body: Center( child: Text( '這是一個文本控件', //文本內(nèi)容 textAlign: TextAlign.center, //居中 maxLines: 1, //最大顯示行數(shù) style: TextStyle( fontSize: 25.0, //字體大小 color: Colors.lightBlue, //字體顏色 ), //樣式 ), ), ), ); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      有語言基礎(chǔ)的同學(xué)相信可以很好理解這些代碼,第一行導(dǎo)入了Material相關(guān)的類庫。程序會先執(zhí)行main()方法,該方法又執(zhí)行了runApp()方法,并將MyTextApp類作為參數(shù)傳遞。而MyTextApp類就是我們自定義的一個類,該類需要去繼承StatelessWidget,并重寫build()方法,該方法需要返回一個組件。具體的代碼我就不一一介紹了,可以先不用理解每一行代碼的意思。其中的Text便是文本組件,只需將值寫入括號,便可以在文本框中顯示,然后是文本框的一些屬性。接下來我們運(yùn)行起來看一下。

      接下來是圖片組件,圖片組件的作用無非就是顯示圖片,在Flutter中,Image有四種方式顯示圖片,我只介紹一種,就是顯示網(wǎng)絡(luò)圖片,其它三種方式?jīng)]有太大差別。

      import 'package:flutter/material.dart'; void main() { runApp(MyImageApp()); } /** * 圖片組件(Image)的使用 */ class MyImageApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Text Demo', home: Scaffold( appBar: AppBar(title: Text('圖片組件的使用')), body: Center( child: Image.network( 'https://www.baidu.com/img/baidu_jgylogo3.gif', //圖片地址 scale: 1.0, //縮放比 ), ), ), ); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      運(yùn)行效果如下:

      列表組件在移動端的開發(fā)中使用非常頻繁,那么在Flutter中,該如何使用ListView呢?

      import 'package:flutter/material.dart'; void main() { runApp(MyListViewApp()); } /** * 列表組件(List)的使用 */ class MyListViewApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Text Demo', home: Scaffold( appBar: AppBar(title: Text('圖片組件的使用')), body: Center( child: Container( height: 200.0, child: ListView( scrollDirection: Axis.horizontal,,//列表方向(縱向) children: [ Container( width: 180.0, color: Colors.lightBlue, ), Container( width: 180.0, color: Colors.amber, ), Container( width: 180.0, color: Colors.deepOrange, ), Container( width: 180.0, color: Colors.deepPurple, ), //Container ], //Widget[] ), ), ), ), ); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      有些同學(xué)看到這樣的代碼可能驚呆了,這么多層的嵌套維護(hù)起來豈不是很麻煩,其實(shí)這也是Dart語法的特點(diǎn),避免不了,但是還是有辦法的,我們可以把ListView單獨(dú)抽出來,這樣主體的代碼將會簡潔很多。

      import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'FlutterApp', home: Scaffold( //主頁 appBar: AppBar(title: Text('FlutterDemo')), //標(biāo)題 body: Center( child: Container( height: 200.0, child: MyList(), //ListView ), //Container ), //主體 ), //Scaffold ); //MaterialApp } } class MyList extends StatelessWidget { @override Widget build(BuildContext context) { return ListView( scrollDirection: Axis.horizontal, children: [ Container( width: 180.0, color: Colors.lightBlue, ), Container( width: 180.0, color: Colors.amber, ), Container( width: 180.0, color: Colors.deepOrange, ), Container( width: 180.0, color: Colors.deepPurple, ), //Container ], //Widget[] ); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      谷歌移動UI框架Flutter教程之Widget

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      現(xiàn)在運(yùn)行看一下效果。

      當(dāng)然,這樣編寫列表在實(shí)際開發(fā)中是不現(xiàn)實(shí)的,我們應(yīng)該讓列表活起來,所以,下面介紹如何實(shí)現(xiàn)動態(tài)列表。

      import 'package:flutter/material.dart'; void main() { runApp(MyApp( items: List < String>.generate(1000, (i) => "Item $i") ) ); } class MyApp extends StatelessWidget { final List items; MyApp({Key key, @required this.items}) :super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'FlutterApp', home: Scaffold( //主頁 appBar: AppBar(title: Text('FlutterDemo')), //標(biāo)題 body: ListView.builder( itemCount: items.length, itemBuilder: (context, index) { return ListTile( title: Text('${items[index]}'), ); }, ), ), //Scaffold ); //MaterialApp } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      這樣就實(shí)現(xiàn)了動態(tài)列表,只不過這個數(shù)據(jù)還是自己提供的,只需要后期通過網(wǎng)絡(luò)獲取數(shù)據(jù)再封裝成集合然后傳遞即可。不懂Dart語法的同學(xué)對于里面的某些代碼可能會覺得難以理解,但是不用擔(dān)心。即使沒有一點(diǎn)Dart語言基礎(chǔ)的同學(xué)也是可以很容易地學(xué)會Flutter的,只不過在某些Dart語法上就只能死記了,記住它,不用管為什么。那么現(xiàn)在來運(yùn)行看下效果。

      第二個列表組件,網(wǎng)格組件,該組件在如今的移動應(yīng)用中也非常常見,最典型的便是系統(tǒng)相冊。那么我們關(guān)心的是在Flutter中該如何去使用GridView呢?通過一個例子來了解一下。

      import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'FlutterApp', home: Scaffold( //主頁 appBar: AppBar(title: Text('FlutterDemo')), //標(biāo)題 body: GridView( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, mainAxisSpacing: 2.0, //縱軸邊距 crossAxisSpacing: 2.0, //橫軸邊距 childAspectRatio: 0.7 //縮放比例(寬高比) ), children: [ Image.network( 'http://img5.mtime.cn/mg/2019/05/31/163641.36482297_270X405X4.jpg', fit: BoxFit.cover), Image.network( 'http://img5.mtime.cn/mg/2019/07/01/091243.35485139_270X405X4.jpg', fit: BoxFit.cover), Image.network( 'http://img5.mtime.cn/mg/2019/06/28/141449.40971533_270X405X4.jpg', fit: BoxFit.cover), Image.network( 'http://img5.mtime.cn/mg/2019/05/31/163641.36482297_270X405X4.jpg', fit: BoxFit.cover), Image.network( 'http://img5.mtime.cn/mg/2019/07/01/091243.35485139_270X405X4.jpg', fit: BoxFit.cover), Image.network( 'http://img5.mtime.cn/mg/2019/06/28/141449.40971533_270X405X4.jpg', fit: BoxFit.cover), ], //Widget[] ) //GridView ), //Scaffold ); //MaterialApp } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      網(wǎng)格組件其實(shí)也非常的簡單,和ListView其實(shí)沒有什么差別,最主要的就是它獨(dú)特的屬性,這些屬性在官網(wǎng)文檔中都有解釋和示例。那么這段代碼運(yùn)行的效果如何呢?我們看一下:

      布局

      Flutter中基本的一些組件就介紹完了,但是光知道如何編寫組件可遠(yuǎn)遠(yuǎn)不夠,UI設(shè)計(jì)中的布局管理也尤為重要,那么,我們繼續(xù)深入,了解一下Flutter中的布局。

      經(jīng)過前面基本組件的學(xué)習(xí),會發(fā)現(xiàn)Flutter無非就是一些組件的嵌套,但注意嵌套級別,不要被自己的代碼搞暈了,那么布局其實(shí)是一樣的。我們看一個例子。

      import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Row Widget Demo', home: Scaffold( appBar: AppBar( title: Text('水平方向布局'), ), //AppBar body: Row( children: [ RaisedButton( onPressed: () {}, color: Colors.redAccent, child: Text('Red Button'), ),RaisedButton( onPressed: () {}, color: Colors.orangeAccent, child: Text('Orange Button'), ),RaisedButton( onPressed: () {}, color: Colors.lightBlue, child: Text('Blue Button'), ), ], //Widget[] ), //Row ), //Scaffold ); //MaterialApp } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      Row即是水平布局,那么水平布局中我們放置了三個按鈕,現(xiàn)在,運(yùn)行看效果。

      會發(fā)現(xiàn) ,這個按鈕的右邊空出了一塊,這是為什么呢?其實(shí)是因?yàn)槲覀兪褂玫氖且粋€不靈活的水平布局,那么既然有不靈活的水平布局,那就肯定會有靈活的水平布局。

      import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Row Widget Demo', home: Scaffold( appBar: AppBar( title: Text('水平方向布局'), ), //AppBar body: Row( children: [ Expanded(child: RaisedButton( onPressed: () {}, color: Colors.redAccent, child: Text('Red Button'), )), Expanded(child: RaisedButton( onPressed: () {}, color: Colors.orangeAccent, child: Text('Orange Button'), )), Expanded(child: RaisedButton( onPressed: () {}, color: Colors.lightBlue, child: Text('Blue Button'), )), ], //Widget[] ), //Row ), //Scaffold ); //MaterialApp } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      我們并沒有對代碼進(jìn)行過多的修改,只是在每個按鈕外部包了一個Expanded組件,那么現(xiàn)在我們來看一下運(yùn)行效果:

      會發(fā)現(xiàn),按鈕成功自適應(yīng)屏幕了,這才是我們想要的效果。

      既然有水平布局,當(dāng)然就有垂直布局。現(xiàn)在通過一個例子來理解一下垂直布局。

      import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Row Widget Demo', home: Scaffold( appBar: AppBar( title: Text('水平方向布局'), ), //AppBar body: Column( children: [ Text('Column 1'), Text('This is Column 2'), Text('Column 3'), ], //Widget ) //Column ), //Scaffold ); //MaterialApp } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      應(yīng)該不難理解,道理是一樣的,現(xiàn)在看一下效果:

      細(xì)心的同學(xué)會發(fā)現(xiàn),它默認(rèn)會有一個居中的對齊方式。但有同學(xué)提出疑問了,這也沒居中啊,這不還是在屏幕的左側(cè)嗎?其實(shí)這個對齊是相對Column來說的,這個Column的大小是由最長的Text組件決定的。通過crossAxisAlignment屬性可以設(shè)置Column的對齊方式。

      使用水平布局和垂直布局雖然可以實(shí)現(xiàn)大部分的布局效果,但是如果要在一張圖片上顯示一段文字,這兩種布局將無法實(shí)現(xiàn)。所以,這里我們學(xué)習(xí)一種層疊布局,它能夠很輕松地實(shí)現(xiàn)這個效果。

      import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { var stack = Stack( alignment: const FractionalOffset(0.5, 0.8), children: [ CircleAvatar( backgroundImage: NetworkImage( 'https://i0.hdslb.com/bfs/archive/79c30cf5850cb9ec9d6129b200145e1644f696f8.jpg@880w_440h.jpg'), radius: 100.0, ), //CircleAvatar Container( decoration: BoxDecoration( color: Colors.lightBlue ), padding: EdgeInsets.all(5.0), child: Text('層疊布局'), ) ], //Widget[] ); //Stack return MaterialApp( title: 'Row Widget Demo', home: Scaffold( appBar: AppBar( title: Text('水平方向布局'), ), //AppBar body: Center( child: stack, ) ), //Scaffold ); //MaterialApp } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      我們首先創(chuàng)建一個組件變量,將我們的圖片和文字都定義在里面,然后通過alignment屬性可以決定文本組件的相對位置,看一下效果:

      最后一個布局,卡片布局。來看例子。

      import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { var card = Card( child: Column( children: [ ListTile( title: Text( '江西省南昌市青云譜區(qū)', style: TextStyle(fontWeight: FontWeight.w500),), subtitle: Text('Temptation:123456789'), leading: Icon(Icons.account_box, color: Colors.lightBlue,), ), new Divider(), ListTile( title: Text( '北京市海淀區(qū)中國科技大學(xué)', style: TextStyle(fontWeight: FontWeight.w500),), subtitle: Text('Temptation:123456789'), leading: Icon(Icons.account_box, color: Colors.lightBlue,), ), new Divider(), ListTile( title: Text( '河南省濮陽市百姓辦公樓', style: TextStyle(fontWeight: FontWeight.w500),), subtitle: Text('Temptation:123456789'), leading: Icon(Icons.account_box, color: Colors.lightBlue,), ) //ListTile ], //Widget[] ), //Column ); //Card return MaterialApp( title: 'Row Widget Demo', home: Scaffold( appBar: AppBar( title: Text('水平方向布局'), ), //AppBar body: Center( child: card ) ), //Scaffold ); //MaterialApp } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      運(yùn)行看效果:

      篇幅有限,關(guān)于Flutter的組件和布局就介紹到這里,接下來還會有一篇關(guān)于Flutter的進(jìn)階博客,感興趣的同學(xué)可以看一看。

      Android Flutter

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:項(xiàng)目之關(guān)于Summernote的圖片處理和基于SpringMVC的文件上傳(10)
      下一篇:(重溫Java注解知識)深入了解Java中的注解
      相關(guān)文章
      日本亚洲免费无线码 | 自拍偷自拍亚洲精品情侣| 亚洲激情黄色小说| 国产亚洲成人在线播放va| 亚洲精品成人片在线观看| 久久久亚洲精华液精华液精华液| 亚洲一区二区三区在线| 亚洲av永久无码精品国产精品 | 亚洲婷婷综合色高清在线| 亚洲一卡2卡三卡4卡有限公司 | 亚洲成a∨人片在无码2023| 亚洲人成免费电影| 中文字幕亚洲第一在线| 久久夜色精品国产亚洲AV动态图| 亚洲情综合五月天| 亚洲A丁香五香天堂网| 亚洲AV日韩AV一区二区三曲| 亚洲av无码专区国产不乱码| 亚洲大成色www永久网址| 亚洲伊人久久大香线蕉啊| 亚洲色大成网站www永久| 久久精品亚洲中文字幕无码麻豆 | 亚洲无删减国产精品一区| 久久精品国产亚洲麻豆| 亚洲级αV无码毛片久久精品| 亚洲伊人久久大香线蕉综合图片| 亚洲精品tv久久久久| 亚洲AV成人潮喷综合网| 亚洲AV无码乱码在线观看牲色| 鲁死你资源站亚洲av| 亚洲AV无码国产一区二区三区| 亚洲乱码无人区卡1卡2卡3| 亚洲日韩精品无码专区加勒比| 亚洲中文字幕久久久一区| 亚洲一线产区二线产区区| 亚洲一区AV无码少妇电影| 亚洲国产美女精品久久久| 久久精品国产亚洲AV电影网| xvideos亚洲永久网址| 亚洲欧洲精品成人久久曰影片 | 相泽亚洲一区中文字幕|