跳到主內容

新增資源和影像

如何在 Flutter 應用中使用影像(及其他資源)。

Flutter 應用可以包含程式碼和資源(有時稱為資原始檔)。資源是指與應用一起打包和部署,並在執行時可訪問的檔案。常見的資源型別包括靜態資料(例如 JSON 檔案)、配置檔案、圖示和影像(JPEG、WebP、GIF、動畫 WebP/GIF、PNG、BMP 和 WBMP)。

指定資源

#

Flutter 使用專案根目錄下的 pubspec.yaml 檔案來識別應用所需的資源。

以下是一個示例

yaml
flutter:
  assets:
    - assets/my_icon.png
    - assets/background.png

要包含目錄下的所有資源,請在目錄名稱後新增 / 字元

yaml
flutter:
  assets:
    - directory/
    - directory/subdirectory/

資源打包

#

flutter 部分下的 assets 子部分指定了應包含在應用中的檔案。每個資源由其所在位置的明確路徑(相對於 pubspec.yaml 檔案)標識。資源的宣告順序無關緊要。所使用的實際目錄名稱(第一個示例中的 assets 或上述示例中的 directory)也不重要。

在構建過程中,Flutter 會將資源放入一個稱為資源包 (asset bundle) 的特殊存檔中,應用在執行時會從中讀取這些資源。

構建時自動轉換資原始檔

#

Flutter 支援在構建應用時使用 Dart 包來轉換資原始檔。為此,請在您的 pubspec 檔案中指定資原始檔和轉換器包。要了解如何執行此操作並編寫自己的資源轉換包,請參閱 在構建時轉換資源

載入資源

#

您的應用可以透過 AssetBundle 物件訪問其資源。

資源包上的兩個主要方法允許您根據邏輯鍵從包中載入字串/文字資源 (loadString()) 或影像/二進位制資源 (load())。邏輯鍵對映到構建時在 pubspec.yaml 檔案中指定的資源路徑。

載入文字資源

#

每個 Flutter 應用都有一個 rootBundle 物件,用於輕鬆訪問主資源包。可以直接使用來自 package:flutter/services.dartrootBundle 全域性靜態變數來載入資源。

但是,建議使用 DefaultAssetBundle 獲取當前 BuildContextAssetBundle,而不是使用隨應用構建的預設資源包;這種方法允許父級 widget 在執行時替換不同的 AssetBundle,這對於本地化或測試場景非常有用。

通常,您會使用 DefaultAssetBundle.of() 來間接載入資源(例如 JSON 檔案)到應用的執行時 rootBundle 中。

Widget 上下文之外,或者當無法獲得 AssetBundle 的控制代碼時,可以使用 rootBundle 直接載入此類資源。例如

dart
import 'package:flutter/services.dart' show rootBundle;

Future<String> loadAsset() async {
  return await rootBundle.loadString('assets/config.json');
}

載入影像

#

要載入影像,請在 widget 的 build() 方法中使用 AssetImage 類。

例如,您的應用可以從之前示例中的資源宣告中載入背景影像

dart
return const Image(image: AssetImage('assets/background.png'));

適配解析度的影像資源

#

Flutter 可以根據當前 裝置畫素比 載入適配解析度的影像。

AssetImage 會將請求的邏輯資源對映到最接近當前 裝置畫素比 的資源上。

為了使此對映生效,資源應按照特定的目錄結構進行排列

.../image.png
.../Mx/image.png
.../Nx/image.png
...etc.

其中 MN 是與所包含影像的標稱解析度相對應的數值識別符號。換句話說,它們指定了影像旨在用於的裝置畫素比。

在此示例中,image.png 被視為主資源,而 Mx/image.pngNx/image.png 被視為變體

假設主資源對應於 1.0 的解析度。例如,考慮以下名為 my_icon.png 的影像資源佈局

.../my_icon.png       (mdpi baseline)
.../1.5x/my_icon.png  (hdpi)
.../2.0x/my_icon.png  (xhdpi)
.../3.0x/my_icon.png  (xxhdpi)
.../4.0x/my_icon.png  (xxxhdpi)

在裝置畫素比為 1.8 的裝置上,會選擇資源 .../2.0x/my_icon.png。對於裝置畫素比為 2.7 的裝置,會選擇資源 .../3.0x/my_icon.png

如果未在 Image widget 上指定渲染影像的寬度和高度,則會使用標稱解析度對資源進行縮放,使其佔據與主資源相同的螢幕空間,只是具有更高的解析度。也就是說,如果 .../my_icon.png 是 72px x 72px,那麼 .../3.0x/my_icon.png 應該是 216px x 216px;但如果未指定寬度和高度,它們都將渲染為 72px x 72px(邏輯畫素)。

適配解析度影像資源的打包

#

您只需要在 pubspec.yamlassets 部分指定主資源或其父目錄即可。Flutter 會自動為您打包變體。每個條目都應對應一個真實檔案,主資源條目除外。如果主資源條目未對應真實檔案,則解析度最低的資源將用作裝置畫素比低於該解析度的裝置的後備資源。不過,該條目仍應包含在 pubspec.yaml 清單中。

任何使用預設資源包的內容在載入影像時都會自動繼承解析度感知。(如果您使用一些較低級別的類,如 ImageStreamImageCache,您也會注意到與縮放相關的引數。)

包依賴中的資源影像

#

要從 package 依賴中載入影像,必須向 AssetImage 提供 package 引數。

例如,假設您的應用程式依賴於一個名為 my_icons 的包,它具有以下目錄結構

.../pubspec.yaml
.../icons/heart.png
.../icons/1.5x/heart.png
.../icons/2.0x/heart.png
...etc.

要載入影像,請使用

dart
return const AssetImage('icons/heart.png', package: 'my_icons');

包本身使用的資源也應按上述方式使用 package 引數進行獲取。

包資源的打包

#

如果所需的資源在包的 pubspec.yaml 檔案中指定,它會自動與應用程式打包在一起。特別是,包本身使用的資源必須在其 pubspec.yaml 中指定。

包也可以選擇在其 lib/ 資料夾中包含未在 pubspec.yaml 檔案中指定的資源。在這種情況下,要打包這些影像,應用程式必須在其 pubspec.yaml 中指定要包含哪些影像。例如,一個名為 fancy_backgrounds 的包可能包含以下檔案

.../lib/backgrounds/background1.png
.../lib/backgrounds/background2.png
.../lib/backgrounds/background3.png

要包含第一個影像,應用程式的 pubspec.yaml 應在其 assets 部分中指定它

yaml
flutter:
  assets:
    - packages/fancy_backgrounds/backgrounds/background1.png

lib/ 是隱含的,因此不應包含在資源路徑中。

如果您正在開發一個包,要載入包內的資源,請在包的 pubspec.yaml 中指定它

yaml
flutter:
  assets:
    - assets/images/

要在您的包內載入影像,請使用

dart
return const AssetImage('packages/fancy_backgrounds/backgrounds/background1.png');

與底層平臺共享資源

#

Flutter 資源可透過 Android 上的 AssetManager 和 iOS 上的 NSBundle 在平臺程式碼中輕鬆訪問。

在 Android 中載入 Flutter 資源

#

在 Android 上,資源可透過 AssetManager API 訪問。例如,在 openFd 中使用的查詢鍵是從 PluginRegistry.Registrar 上的 lookupKeyForAssetFlutterView 上的 getLookupKeyForAsset 獲取的。開發外掛時可以使用 PluginRegistry.Registrar,而在開發包含平臺檢視的應用時,FlutterView 將是更好的選擇。

作為示例,假設您在 pubspec.yaml 中指定了以下內容

yaml
flutter:
  assets:
    - icons/heart.png

這反映了您的 Flutter 應用中的以下結構。

.../pubspec.yaml
.../icons/heart.png
...etc.

要從 Java 外掛程式碼訪問 icons/heart.png,請執行以下操作

java
AssetManager assetManager = registrar.context().getAssets();
String key = registrar.lookupKeyForAsset("icons/heart.png");
AssetFileDescriptor fd = assetManager.openFd(key);

在 iOS 中載入 Flutter 資源

#

在 iOS 上,資源可透過 mainBundle 訪問。例如,在 pathForResource:ofType: 中使用的查詢鍵是從 FlutterPluginRegistrar 上的 lookupKeyForAssetlookupKeyForAsset:fromPackage: 獲取的,或者是從 FlutterViewController 上的 lookupKeyForAsset:lookupKeyForAsset:fromPackage: 獲取的。開發外掛時可以使用 FlutterPluginRegistrar,而在開發包含平臺檢視的應用時,FlutterViewController 將是更好的選擇。

作為示例,假設您有上述的 Flutter 設定。

要從 Objective-C 外掛程式碼訪問 icons/heart.png,您可以執行以下操作

objc
NSString* key = [registrar lookupKeyForAsset:@"icons/heart.png"];
NSString* path = [[NSBundle mainBundle] pathForResource:key ofType:nil];

要從 Swift 應用訪問 icons/heart.png,您可以執行以下操作

swift
let key = controller.lookupKey(forAsset: "icons/heart.png")
let mainBundle = Bundle.main
let path = mainBundle.path(forResource: key, ofType: nil)

有關更完整的示例,請參閱 pub.dev 上 Flutter video_player 外掛 的實現。

在 Flutter 中載入 iOS 影像

#

當透過 將 Flutter 新增到現有的 iOS 應用 中來實現 Flutter 時,您可能擁有想要在 Flutter 中使用的 iOS 託管影像。要實現這一點,請使用 平臺通道 將影像資料以 FlutterStandardTypedData 的形式傳遞給 Dart。

平臺資源

#

在其他情況下,您可能需要直接在平臺專案中處理資源。以下是兩種在 Flutter 框架載入並執行之前使用資源的常見情況。

更新應用圖示

#

更新 Flutter 應用的啟動圖示與更新原生 Android 或 iOS 應用中的啟動圖示方式相同。

Launch icon

Android

#

在 Flutter 專案的根目錄中,導航到 .../android/app/src/main/res。各種點陣圖資原始檔夾(如 mipmap-hdpi)已經包含了名為 ic_launcher.png 的佔位符影像。請按照 Android 開發者指南 指定的每種螢幕密度的建議圖示尺寸,用您所需的資源替換它們。

Android icon location

iOS

#

在 Flutter 專案的根目錄中,導航到 .../ios/RunnerAssets.xcassets/AppIcon.appiconset 目錄中已經包含了佔位符影像。請按照 Apple 人機介面指南 指定的檔名,用相應尺寸的影像替換它們。請保持原始檔名不變。

iOS icon location

更新啟動螢幕

#

Launch screen

Flutter 還使用原生平臺機制在 Flutter 框架載入時為您的 Flutter 應用繪製過渡啟動螢幕。此啟動螢幕將持續顯示,直到 Flutter 渲染您的應用程式的第一幀。

Android

#

要向您的 Flutter 應用新增啟動螢幕(也稱為“閃屏”),請導航到 .../android/app/src/main。在 res/drawable/launch_background.xml 中,使用此 圖層列表 drawable XML 來自定義啟動螢幕的外觀。現有的模板在註釋程式碼中提供了一個在白色啟動螢幕中間新增影像的示例。您可以取消註釋該程式碼或使用其他 drawables 來達到預期的效果。

有關更多詳細資訊,請參閱 向您的 Android 應用新增閃屏

iOS

#

要將影像新增到“閃屏”中心,請導航到 .../ios/Runner。在 Assets.xcassets/LaunchImage.imageset 中,放入名為 LaunchImage.pngLaunchImage@2x.pngLaunchImage@3x.png 的影像。如果您使用不同的檔名,請更新同一目錄中的 Contents.json 檔案。

您也可以透過開啟 .../ios/Runner.xcworkspace 在 Xcode 中完全自定義您的啟動螢幕故事板。在專案導航器中導航到 Runner/Runner,並透過開啟 Assets.xcassets 放入影像,或者使用 LaunchScreen.storyboard 中的介面構建器進行任何自定義。

Adding launch icons in Xcode

有關更多詳細資訊,請參閱 向您的 iOS 應用新增閃屏