當前位置:首頁>時尚>ui布局詳細講解(一個月帶你入門Flutter)
發(fā)布時間:2024-09-05閱讀(22)

Flutter系列的文章我會持續(xù)更新一個月左右,力求利用1個月帶大家入門Flutter,抓住這波技術(shù)風(fēng)口,歡迎大家關(guān)注。同時如果覺得這里代碼排版不是很舒服的讀者可以關(guān)注我的微信公眾號“IT工匠”,我會同步更新,另外微信公眾號上還有很多互聯(lián)網(wǎng)必備資源(涉及算法、數(shù)據(jù)結(jié)構(gòu)、java、深度學(xué)習(xí)、計算機網(wǎng)絡(luò)、python、Android等互聯(lián)網(wǎng)技術(shù)資料),歡迎大家關(guān)注、交流。
摘要本文通過一個簡單的實例來逐步為大家介紹如何在Flutter中構(gòu)建漂亮的布局,通過本文你將會了解到以下幾點:
本文檔主要介紹如何在Flutter中進行布局,你將最終會構(gòu)建一個下圖這樣的頁面:

本文將一步一步帶你構(gòu)建一個像上圖那樣的頁面。
第0步:創(chuàng)建一個Flutter項目Widget build(BuildContext context) { return MaterialApp( title: Flutter layout demo, home: Scaffold( appBar: AppBar( title: Text(Flutter layout demo), ), body: Center( child: Text(Hello World), ), )); }
設(shè)置完成后運行起來效果如下圖所示:

第一步是將整個頁面布局分解為基本元素,主要從以下幾點入手
那么我們先來看一下整個頁面的主要組成部分:

可以看到,整個頁面的主要組成部分就是由紅色框標注出來的4部分,這4部分位于同一個列(Column),分別是:1個Image、2個Row、1個Text。
再深入地分析一下每一個行(Row):

可以看到,由于第1個列(Column)占據(jù)了整個行的大部分空間,所以其應(yīng)該被Expanded Widget包裹。

經(jīng)過以上的分析,我們將一個復(fù)雜的頁面分解為了多個簡單的組成部分,這樣可以簡化整個頁面的實現(xiàn),為了避免布局代碼的混亂,我們應(yīng)該利用變量和函數(shù)來構(gòu)建布局的子部分,這一點我會在下面的代碼中進行演示。
第2步:實現(xiàn)第一行(title Row)直接給出代碼,具體的解釋在代碼的注釋中,大家注意看注釋:
Widget titleSection = Container( //為整個Widget(即這一行)的所有所有方向設(shè)置32px的填充 padding: const EdgeInsets.all(32), child: Row( children: [ Expanded( /** 將Column放置在Expanded中,由于Expanded會默認占據(jù)所有當前Row的空閑可用空間,所以這個Column也會自然被拉伸的占據(jù)完所有當前Row可用的空閑空間。 */ child: Column( /**將Column的crossAxisAlignment屬性設(shè)置為CrossAxisAlignment.start以保證這個列中的元素(即children屬性中的Widget)在水平方向上排列在當前Column的起始位置 */ crossAxisAlignment: CrossAxisAlignment.start, children: [ /** 將這個Text放在Container中的目的是通過Container來添加填充(padding) */ Container( padding: const EdgeInsets.only(bottom: 8), child: Text( Oeschinen Lake Campground, style: TextStyle( fontWeight: FontWeight.bold, ), ), ), Text( Kandersteg, Switzerland, style: TextStyle( color: Colors.grey[500], ), ), ], ), ), /** 最后的2個元素分別是1個Icon和1個Text,分別用來顯示星星和數(shù)字 */ Icon( Icons.star, color: Colors.red[500], ), Text(41), ], ),);
直接將上面的變量titleSection放在在app body中即可:
@override Widget build(BuildContext context) { return MaterialApp( title: Flutter layout demo, debugShowCheckedModeBanner: false, home: Scaffold( appBar: AppBar( title: Text(Flutter layout demo), ), body: Column( children: <Widget>[titleSection], ))); }
注意,這里通過使用變量titleSection來達到簡化布局代碼的目的,這樣就不會導(dǎo)致MaterialApp(..)中的代碼太長、太混亂。
運行起來的效果如下圖所示:

按鈕行(button section)有3個列,每個列都是同樣的布局組成:1個Icon、1個Text。這一行中的列之間的間距都是均勻的,由于構(gòu)建每一列的代碼幾乎相同,因此創(chuàng)建一個名為buildbuttoncolumn()的私有方法,該方法接收一個顏色(Color)參數(shù)、一個圖標(Icon)參數(shù)和1個文本(Text)參數(shù),并返回一個具有以給定顏色繪制的Widget的列(Column),代碼如下:
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { // ··· } Column _buildButtonColumn(Color color, IconData icon, String label) { return Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icon, color: color), Container( margin: const EdgeInsets.only(top: 8), child: Text( label, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w400, color: color, ), ), ), ], ); }}
_buildButtonColumn()方法將Icon直接添加到Column中,而Text是先用Container進行包裹,然后再將Container添加到Column中,這樣做的目的是借助Container為Text設(shè)置頂部填充(padding),這樣就不至于Text和Icon距離過近。
完成了_buildButtonColumn()函數(shù)之后,我們只需要在需要構(gòu)建列(Column)的時候調(diào)用該函數(shù)并傳入對應(yīng)的3個參數(shù)即可構(gòu)建出我們需要的列:
Color color = Theme.of(context).primaryColor;Widget buttonSection = Container( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildButtonColumn(color, Icons.call, CALL), _buildButtonColumn(color, Icons.near_me, ROUTE), _buildButtonColumn(color, Icons.share, SHARE), ], ),);
注意這里設(shè)置Row的mainAxisAlignment屬性值為MainAxisAlignment.spaceEvenly,目的是讓Row中的列均勻地占滿整個行的可用空間。
然后將變量buttonSection放在app body中:
return MaterialApp( title: Flutter layout demo, debugShowCheckedModeBanner: false, home: Scaffold( appBar: AppBar( title: Text(Flutter layout demo), ), body: Column( children: <Widget>[titleSection, buttonSection], )));
運行效果圖如下圖所示:

將Text部分定義為一個變量,然后將Text放置在一個Container中,并為Container設(shè)置padding屬性:
Widget textSection = Container( padding: const EdgeInsets.all(32), child: Text( Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese Alps. Situated 1,578 meters above sea level, it is one of the larger Alpine Lakes. A gondola ride from Kandersteg, followed by a half-hour walk through pastures and pine forest, leads you to the lake, which warms to 20 degrees Celsius in the summer. Activities enjoyed here include rowing, and riding the summer toboggan run., softWrap: true, ),);
注意這里設(shè)置softwrap屬性值為true,這樣可以保證文字可以在單詞分界的地方換行而不是在單詞中間換行。
然后將上面的textSection變量放在app body中:
return MaterialApp( title: Flutter layout demo, debugShowCheckedModeBanner: false, home: Scaffold( appBar: AppBar( title: Text(Flutter layout demo), ), body: Column( children: <Widget>[titleSection, buttonSection, textSection], )));
運行效果圖如下圖所示:

到現(xiàn)在為止我們已經(jīng)完成了4行中的3行,只剩下圖像那行還沒實現(xiàn),這一步我們來實現(xiàn)圖像的顯示:

flutter: uses-material-design: true assets: - images/lake.jpg
然后我們就可以在代碼中引用該圖了:
return MaterialApp( title: Flutter layout demo, debugShowCheckedModeBanner: false, home: Scaffold( appBar: AppBar( title: Text(Flutter layout demo), ), body: Column( children: <Widget>[ Image.asset( images/lake.jpg, width: 600, height: 240, fit: BoxFit.cover, ), titleSection, buttonSection, textSection ], )));
運行起來效果如下:

我們來看前幾步完成之后的最終代碼:
return MaterialApp( title: Flutter layout demo, debugShowCheckedModeBanner: false, home: Scaffold( appBar: AppBar( title: Text(Flutter layout demo), ), body: Column( children: <Widget>[ Image.asset( images/lake.jpg, width: 600, height: 240, fit: BoxFit.cover, ), titleSection, buttonSection, textSection ], )));
注意,我們將body的屬性值設(shè)置為了Column,然后在Column中放置了我們實現(xiàn)的幾個子Widget,現(xiàn)在我們換種方式,使用ListView來取代這個Column:
return MaterialApp( title: Flutter layout demo, debugShowCheckedModeBanner: false, home: Scaffold( appBar: AppBar( title: Text(Flutter layout demo), ), body: ListView( children: [ Image.asset( images/lake.jpg, width: 600, height: 240, fit: BoxFit.cover, ), titleSection, buttonSection, textSection ], )));
效果如下:

可以看到,使用Column和使用ListView的靜態(tài)視覺效果是一樣的,那我們到底應(yīng)該使用Column還是ListView呢?二者的區(qū)別在哪里呢?答案就在”動態(tài)”,二者在動態(tài)下的效果是不一樣的,再具體點,使用Column構(gòu)建的Widget是不支持滾動的,即不支持進行上下或者左右的滾動事件,而使用ListView會支持滾動事件,就像下面這樣:

歡迎分享轉(zhuǎn)載→http://www.avcorse.com/read-405490.html
下一篇:化完妝噴脖子的是什么
Copyright ? 2024 有趣生活 All Rights Reserve吉ICP備19000289號-5 TXT地圖HTML地圖XML地圖