來吧!Flutter(11) — 初探 Image

Andy Lu
Flutter Taipei
Published in
6 min readAug 13, 2020

--

圖片,是 App 中最常出現的 Widget 之一,依來源分類可分為兩種:本機圖片、網路圖片。針對兩種圖片來源 Flutter 都能使用 Image Widget 來處理它們。

本機圖片

介紹如何使用本機圖片之前,我們需要了解 Flutter 的 assets 系統。

assets

在 pubspec.yaml 檔案中,我們可以加上

flutter:
assets:
- assets\good_morning.png
- assets\good_night.png

這代表什麼意思呢?

我們將兩張存放於 assets 資料夾的圖片,分別為 good_morning.png 以及 good_night.png 加入至系統中,於是我們就可以在程式中呼叫這兩張圖片。

呼叫方法

Image(image: AssetImage('asset image path'));或是Image.asset('asset image path')

其中,Image 建構子的 image 屬性代入的是 ImageProvider,因為我們需要顯示存放在 asset 裡面的圖檔,所以這邊使用 AssetImage 代入。

Flutter 針對 asset image 提供了另一個建構子 Image.asset,我們只需要將 asset 的路徑代入即可。AssetImage 已經被包在 Image.asset 中。

AssetImage 類

在 App 開發中,我們常常會根據不同裝置解析度來使用不同大小的圖片,Flutter 的 AssetImage 類也提供了相同的功能。

在 asset 的資料夾中,我們可以根據不同的像素密度 (Pixel Densities) 來擺放相關的圖片。 例如:

good_morning.png
1.5x/good_morning.png
2.0x/good_morning.png
good_night.png
1.5x/good_night.png
2.0x/good_morning.png

Android 開發者可能不太熟悉像素密度的倍數,一般我們都是以 MDPI、HDMI、XHDPI… 代表,

換算值,我們可以參考下圖,

Relative sizes for bitmaps at different density sizes

網路圖片

除了來自 assets 的圖片外,Image 類 也可以支援網路圖片

假設有一張來自網路的圖片,網址如下

https://cdn.pixabay.com/photo/2015/07/11/23/02/plane-841441_960_720.jpg

我們要如何顯示網路圖片呢?

Image(image: NetworkImage('Image URI'));Image.network('Image URI')

其中,NetworkImage 也是 ImageProvider 的類別之一。

同時,Image 也提供了 Image.network 建構子,將 NetworkImage 包在其中。

但是,如果圖片下載比較慢,或是沒有網路,那麼圖片就會顯示空白。

要怎麼做呢?

在 Image 以及 Image.network 中皆含有一個名為 loadingBuilder 的屬性,我們可以在 loadingBuilder 中增加當圖片尚未完全下載時,應該顯示什麼。如下:

  • loadingBuilder 的型別是 ImageLoadingBuilder,其建構子如下
typedef ImageLoadingBuilder = Widget Function(
BuildContext context,
Widget child,
ImageChunkEvent loadingProgress,
);

這邊可以看到 ImageLoadingBuilder 前方的關鍵字 typedef,表示這是函數類型的別名。在 Dart 中一般用在定義 callback 的介面 (interface), loadingBuilder 被呼叫時,會代入三個參數。

其中,Widget 就是這個 Image,而 ImageChunkEvent 則是每一次呼叫 loadingBuilder 帶進來下載的資訊。

ImageChunkEvent 裡面有兩個屬性:cumulativeBytesLoaded 以及 expectedTotalBytes。

一個是累積下載量,另一個則是預期下載量。

最後,當下載完成時,ImageChunkEvent 為 null。

frameBuilder

除了 loadingBuilder 以外,Image class 還提供了 frameBuilder。frameBuilder 可以在下載完成之後,繪製動畫。如下:

小結

在 Image 類中,提供不同的 ImageProvider 處理不同的圖片來源使用,如本篇文章的本機圖片及網路圖片 。

使用本機圖片時,我們可以針對不同的像素密度,來使用不同大小的圖片,我們只要在 asset 資料夾下分別將不同像素密度的圖片放在相對應的資料夾中,Flutter 即可自動尋找適當的圖片。

另外,我們還可以使用 loadingBuilder 或是 frameBuilder 在圖片讀取的時候,做轉場的效果。

Image 類除了提供 Image.asset、Image.network 這兩個本篇文章所介紹的建構子外,還有 Image.file 以及 Image.memory,我們將在後面的文章繼續討論這兩個 Image的建構子。

如果這篇文章有幫助到你,別忘了幫我拍拍手。

謝謝

參考

Flutter — Adding assets and images

Flutter — loadingBuilder

Flutter — frameBuilder

Android — Screen Densities

iOS — Images Size and Resolution

--

--

Andy Lu
Flutter Taipei

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