來吧!Flutter(7)-Row/Column

橫的還是直的?

Andy Lu
Flutter Taipei

--

Flutter 有為數眾多的佈局 Widget,其中最常用到的莫過於 Column 以及 Row Widget。因為是佈局 Widget,所以本身是沒有畫面的,必須要將需要顯示的 Widget 放在其 children 中。

除了可以將基本的 Widget 放在 children 中,還可以依照需求將複雜的 Widget 也放在其中,例如可以將 Row 放在 Column 中。

另外,可以針對其 children 設定 align(對齊),也可以拉伸其 children widget。

舉例來說:下方的畫面,是由一個 Column 裡面包含著四個子 widget,其中第一個子 Widget 是 Row。

程式碼:

Overflowed

Column 與 Row 都是屬於不可以捲動的 Widget,在這兩個 Widget 中,能擺放的大小就是 Parent Widget 的大小,如上圖,最外層的 Column 最大高度是 Scaffold body 的高度,Column 裡面的 Row 最大寬度則是 Column 的寬度。如果 Children 裡面擺放的內容超過最大可擺放的大小,在 debug 模式底下則會顯示黃色警示線(XXX OVERFLOWED),如下圖。

那麼,該如何解決 Overflowed 的問題呢?因為 Column 與 Row 皆不可捲動,所以超出畫面所能繪製的部分,則將無法顯示,所以只要將 ColumnRow 利用 ***SingleChildScrollView Widget***包起來,在此 Widget 底下的子 Widget 就會成為可以捲動的,如此就可以解決 Overflowed 的問題。

或是可以利用 ListView Widget 來解決。

程式碼:

對齊

Column 的寬度是子 widget 的最大寬度,高度則是父 widget 的最大高度。

反之,Row 的高度是子 Widget 的最大高度,寬度則是父 widget 的最大寬度。

在 Column 以及 Row 中,提供了對齊的屬性:mainAxisAligmnent, crossAxisAlignment。

我們可以利用這兩個屬性改變對齊的方式。

mainAxisAlignment

就字面上意思來看,是主軸的對齊。有什麼作用呢?

首先,mainAxisAlignment 有下列幾個值:start, center, end, spaceAround, spaceEvenly, spaceBetween,下面分別使用這些值來示範。

  • start(預設值)

當沒有設定 mainAxisAlignment 時,預設是 start。由下方的示意圖可以看出,start 是從左上角開始繪製。

  • center

mainAxisAlignment.center 是會將 child widget 置中。

  • end

mainAxisAlignment.end 是將 child 放置在最底下。

另外三個值:spaceAround, spaceEvenly, spaceBetween則是跟子 Widget 的間隔有關係。

  • spaceAround

將空間平均分配,其中第一個以及最後一個子 widget 都只有一半的空間。

  • spaceEvenly

與 spaceAround 不同,所有的子 widget 都有相同大小的間隔。

  • spaceBetween

將第一個 Widget 與最後一個 Widget 分別放在最前與最後,其他的部分平均分配。

crossAxisAlignment

crossAxisAlignment 與 mainAxisAlignment 是相對的,如果是 Column,則是控制橫向;反之,Row 是控制縱向。

因 column 的寬度是跟子 widget 的最大寬度相同,Row 的高度則是跟子 widget 的最大高度相同。 在上方的範例中,column 所有子 widget 都是相同寬度,所以 Column 的寬度與每一個圖片的寬度都與相同,所以 crossAsisAlignment 是沒有作用的。

如果需要使用 crossAxisAlignment 屬性,Column 或是 Row 內子 Widget 的大小就不能一樣。

如下範例,我將第一張圖片的大小限制移掉。

可以發現,第一張圖片的寬度填滿了整個畫面,其餘的圖片則是放在畫面的中間。

  • center(預設值)

Column 與 Row 的預設值都是 center,如上圖所示。

  • start

將所有子 widget 的開始端與父 widget 的開始端對齊。如範例,因父 widget 的寬度是整個畫面,故子 widget 的開始端對齊最左邊。

  • end

與 start 相反,所有子 widget 往最末端對齊,在此範例為向右對齊。

  • stretch

將子 widget 的寬度拉長至與父 widget 的寬度同寬。

在這邊,我將第二張圖不使用 Card 包起來,直接將 Image 放在 children 中,可以發現,stretch 對於第二張圖片沒有作用,其三四張圖片的寬度皆被拉長。

原因是 Image 為固定高度,所以大小不會因為父類別而變動,Card 是動態大小,會依照子類別的大小而變動尺寸。

小記

Column 與 Row 是在 Flutter 中最普遍的 Widget,利用 Column 與 Row 可以將子類別按照順序排列,並且可以設定對齊方式。

使用上需要注意如果子 Widget 的尺寸太大,超過了父 widget 的大小,那麼就會發生 overflowed 的情況。可以利用 SingleChildScorllView 或是 ListView 來解決,或是子 widget 設定小一點(笑)

那麼,Column 與 Row 的介紹就到這邊,如果有問題的歡迎跟我討論。

上面的範例都是以 Column 做示範,大家也可以使用 Row 來操作看看。

最後,範例中使用的圖片皆是使用https://mixkit.co/free-stock-art/ 提供的免費圖片。

謝謝收看

--

--

Andy Lu
Flutter Taipei

Android/Flutter developer, Kotlin Expert, like to learn and share.