Flutter 構(gòu)建布局

2020-08-27 14:46 更新

第0步: 設(shè)置

首先, 獲取代碼:

  • 確保您已經(jīng)安裝好了 set up 您的Flutter環(huán)境.
  • 創(chuàng)建一個(gè)基本的Flutter應(yīng)用程序.

接下來,將圖像添加到示例中:

  • 在工程根目錄創(chuàng)建一個(gè) images 文件夾.
  • 添加一張圖片. (請注意,wget不能保存此二進(jìn)制文件。)
  • 更新 pubspec.yaml 文件以包含 assets 標(biāo)簽. 這樣才會(huì)使您的圖片在代碼中可用。


第一步: 繪制布局圖

第一步是將布局拆分成基本的元素:

  • 找出行和列.
  • 布局包含網(wǎng)格嗎?
  • 有重疊的元素嗎?
  • 是否需要選項(xiàng)卡?
  • 注意需要對齊、填充和邊框的區(qū)域.

首先,確定更大的元素。在這個(gè)例子中,四個(gè)元素排列成一列:一個(gè)圖像,兩個(gè)行和一個(gè)文本塊

diagramming the rows in the lakes screenshot

接下來,繪制每一行。第一行稱其為標(biāo)題部分,有三個(gè)子項(xiàng):一列文字,一個(gè)星形圖標(biāo)和一個(gè)數(shù)字。它的第一個(gè)子項(xiàng),列,包含2行文字。 第一列占用大量空間,所以它必須包裝在Expanded widget中。

diagramming the widgets in the Title section

第二行稱其為按鈕部分,也有3個(gè)子項(xiàng):每個(gè)子項(xiàng)都是一個(gè)包含圖標(biāo)和文本的列。

diagramming the widgets in the button section

一旦拆分好布局,最簡單的就是采取自下而上的方法來實(shí)現(xiàn)它。為了最大限度地減少深度嵌套布局代碼的視覺混淆,將一些實(shí)現(xiàn)放置在變量和函數(shù)中。


Step 2: 實(shí)現(xiàn)標(biāo)題行

首先,構(gòu)建標(biāo)題部分左邊欄。將Column(列)放入Expanded中會(huì)拉伸該列以使用該行中的所有剩余空閑空間。 設(shè)置crossAxisAlignment屬性值為CrossAxisAlignment.start,這會(huì)將該列中的子項(xiàng)左對齊。

將第一行文本放入Container中,然后底部添加8像素填充。列中的第二個(gè)子項(xiàng)(也是文本)顯示為灰色。

標(biāo)題行中的最后兩項(xiàng)是一個(gè)紅色的星形圖標(biāo)和文字“41”。將整行放在容器中,并沿著每個(gè)邊緣填充32像素

這是實(shí)現(xiàn)標(biāo)題行的代碼。

Note: If you have problems, you can check your code against lib/main.dart on GitHub.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Widget titleSection = new Container(
      padding: const EdgeInsets.all(32.0),
      child: new Row(
        children: [
          new Expanded(
            child: new Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                new Container(
                  padding: const EdgeInsets.only(bottom: 8.0),
                  child: new Text(
                    'Oeschinen Lake Campground',
                    style: new TextStyle(
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
                new Text(
                  'Kandersteg, Switzerland',
                  style: new TextStyle(
                    color: Colors.grey[500],
                  ),
                ),
              ],
            ),
          ),
          new Icon(
            Icons.star,
            color: Colors.red[500],
          ),
          new Text('41'),
        ],
      ),
    );
  //...
}

提示: 將代碼粘貼到應(yīng)用程序中時(shí),縮進(jìn)可能會(huì)變形。您可以通過右鍵單擊,選擇 Reformat with dartfmt 來在IntelliJ中修復(fù)此問題?;蛘撸诿钚兄?,您可以使用 dartfmt。

提示: 為了獲得更快的開發(fā)體驗(yàn),請嘗試使用Flutter的熱重載功能。 熱重載允許您修改代碼并查看更改,而無需完全重新啟動(dòng)應(yīng)用程序。 IntelliJ的Flutter插件支持熱重載,或者您可以從命令行觸發(fā)。 有關(guān)更多信息,請參閱Hot Reloads vs 應(yīng)用程序重新啟動(dòng)。


第3步: 實(shí)現(xiàn)按鈕行

按鈕部分包含3個(gè)使用相同布局的列 - 上面一個(gè)圖標(biāo),下面一行文本。該行中的列平均分布行空間, 文本和圖標(biāo)顏色為主題中的primary color,它在應(yīng)用程序的build()方法中設(shè)置為藍(lán)色:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //...

    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),

    //...
}

由于構(gòu)建每個(gè)列的代碼幾乎是相同的,因此使用一個(gè)嵌套函數(shù),如buildButtonColumn,它會(huì)創(chuàng)建一個(gè)顏色為primary color,包含一個(gè)Icon和Text的 Widget 列。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //...

    Column buildButtonColumn(IconData icon, String label) {
      Color color = Theme.of(context).primaryColor;

      return new Column(
        mainAxisSize: MainAxisSize.min,
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          new Icon(icon, color: color),
          new Container(
            margin: const EdgeInsets.only(top: 8.0),
            child: new Text(
              label,
              style: new TextStyle(
                fontSize: 12.0,
                fontWeight: FontWeight.w400,
                color: color,
              ),
            ),
          ),
        ],
      );
    }
  //...
}

構(gòu)建函數(shù)將圖標(biāo)直接添加到列(Column)中。將文本放入容器以在文本上方添加填充,將其與圖標(biāo)分開。

通過調(diào)用函數(shù)并傳遞icon和文本來構(gòu)建這些列。然后在行的主軸方向通過 MainAxisAlignment.spaceEvenly 平均的分配每個(gè)列占據(jù)的行空間。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //...

    Widget buttonSection = new Container(
      child: new Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          buildButtonColumn(Icons.call, 'CALL'),
          buildButtonColumn(Icons.near_me, 'ROUTE'),
          buildButtonColumn(Icons.share, 'SHARE'),
        ],
      ),
    );
  //...
}


第4步:實(shí)現(xiàn)文本部分

將文本放入容器中,以便沿每條邊添加32像素的填充。softwrap屬性表示文本是否應(yīng)在軟換行符(例如句點(diǎn)或逗號)之間斷開。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //...

    Widget textSection = new Container(
      padding: const EdgeInsets.all(32.0),
      child: new 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,
      ),
    );
  //...
}


第5步:實(shí)現(xiàn)圖像部分

四列元素中的三個(gè)現(xiàn)在已經(jīng)完成,只剩下圖像部分。該圖片可以在Creative Commons許可下在線獲得, 但是它非常大,且下載緩慢。在步驟0中,您已經(jīng)將該圖像包含在項(xiàng)目中并更新了pubspec文件,所以現(xiàn)在可以從代碼中直接引用它:

body: new ListView(
  children: [
    new Image.asset(
      'images/lake.jpg',
      height: 240.0,
      fit: BoxFit.cover,
    ),
    // ...
  ],
)

BoxFit.cover 告訴框架,圖像應(yīng)該盡可能小,但覆蓋整個(gè)渲染框


Step 6: 整合

在最后一步,你將上面這些組裝在一起。這些widget放置到ListView中,而不是列中,因?yàn)樵谛≡O(shè)備上運(yùn)行應(yīng)用程序時(shí),ListView會(huì)自動(dòng)滾動(dòng)。

//...
body: new ListView(
  children: [
    new Image.asset(
      'images/lake.jpg',
      width: 600.0,
      height: 240.0,
      fit: BoxFit.cover,
    ),
    titleSection,
    buttonSection,
    textSection,
  ],
),
//...


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號