新增資源和圖片
Flutter 應用程式包含程式碼和 assets(也為資源)。資源是被打包到應用程式安裝套件中,可以在執行時訪問的一種檔案。常見的資源型別包括靜態資料(例如 JSON 檔案),設定檔案,圖示和圖片(JPEG,WebP,GIF,動畫 WebP / GIF,PNG,BMP 和 WBMP)。
指定資源
Flutter 使用 pubspec.yaml
檔案,位於專案根目錄,來識別應用程式所需的資源。
下面舉個例子:
flutter:
assets:
- assets/my_icon.png
- assets/background.png
如果要包含一個目錄下的所有 assets,需要在目錄名稱的結尾加上 /
:
flutter:
assets:
- directory/
- directory/subdirectory/
Asset bundling (應用打包資源)
yaml
檔案 flutter
下面的 assets
部分指定了需要包含在應用中的檔案。每個資源都透過相對於 pubspec.yaml
檔案所在位置的路徑進行標識。資源的宣告順序是無關緊要的。資源的實際目錄可以是任意資料夾(在第一個範例中是 assets
,其他的是 directory
)
在一次建立中,Flutter 將 assets 放到 asset bundle 的特殊歸檔中,以便應用在執行時讀取它們。
載入 assets
你的應用程式可以透過 AssetBundle
物件訪問其資源。
Asset bundle 透過指定一個邏輯鍵(key),允許你讀取 string/text(loadString
)和 image/binary(load
)。在編譯期間,這個邏輯鍵(key)會對映在 pubspec.yaml
中指定的資源路徑。
載入文字 assets
每個 Flutter 應用程式都有一個 rootBundle
物件,可以輕鬆訪問主資源 bundle 。還可以直接使用
package:flutter/services.dart
中全域靜態的 rootBundle
來載入資源。
但是,如果獲取當前 BuildContext
的 AssetBundle
,建議使用 DefaultAssetBundle
。這種方式不是使用應用程式建立的預設資源 bundle,而是讓父級 widget 在執行時替換的不同的 AssetBundle,這對於本地化或測試場景很有用。
通常,你可以從應用程式執行時的 rootBundle
中,間接使用 DefaultAssetBundle.of()
來載入資源(例如 JSON 檔案)。
在 Widget 上下文之外,或 AssetBundle 的句柄不可用時,你可以使用 rootBundle
直接載入這些 assets,例如:
import 'package:flutter/services.dart' show rootBundle;
Future<String> loadAsset() async {
return await rootBundle.loadString('assets/config.json');
}
載入圖片
你可以在 build()
方法中使用 AssetImage
載入圖片。
舉個例子,下面的程式碼載入了先前宣告的背景圖片:
return const Image(image: AssetImage('assets/background.png'));
解析度自適應圖片資源
Flutter 可以為當前裝置載入適合其 裝置畫素比 的影象。
AssetImage
可以將請求資源對映到最接近當前
裝置畫素比 的資源。
為了使這種對映起作用,資源應該根據特定的目錄結構來儲存:
.../image.png
.../Mx/image.png
.../Nx/image.png
...etc.
其中 M 和 N 是數字識別符號,對應於其中包含的影象的解析度,換句話說,它們指定不同裝置畫素比例的圖片。
在範例中,image.png
是 主資源,而 Mx/image.png
和 Nx/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
是 72 px 乘 72 px,那麼 .../3.0x/my_icon.png
應該是 216 px 乘 216 px;但如果未指定寬度和高度,它們都將渲染為 72 px 乘 72 px(以邏輯畫素為單位)。
Bundling of resolution-aware image assets
你只需要在 pubspec.yaml
的 assets
部分指定主要資源,
Flutter 會自動幫你繫結其他變體。在 pubspec.yaml
中資源部分的每一項都應與實際檔案相對應,除過主資源節點。當主資源缺少某個檔案時,會按解析度從低到高的順序去選擇,也就是說 1x 中沒有的話會在 2x 中找,2x 中還沒有的話就在 3x 中找。該條目需要在 pubspec.yaml
中指定。
使用預設的資源 bundle 載入資源時,系統會自動處理解析度等。(如果你使用一些更低級別的類,如 ImageStream
或
ImageCache
,你需要注意 scale 相關的引數)。
依賴套件中的資源圖片
載入依賴 package 中的影象,必須給 AssetImage
提供 package
引數。
例如,你的應用程式依賴於一個名為 my_icons
的 package,它的目錄結構如下:
.../pubspec.yaml
.../icons/heart.png
.../icons/1.5x/heart.png
.../icons/2.0x/heart.png
...etc.
然後載入 image, 使用:
return const AssetImage('icons/heart.png', package: 'my_icons');
package 使用本身的 Assets 也需要加上 package
引數來獲取。
打包 assets
如果期望的資源檔案被指定在 package 的 pubspec.yaml
檔案中,它會被自動打包到應用程式中。特別是,package 本身使用的資源必須在 pubspec.yaml
中指定。
package 也可以選擇在其 lib/
資料夾中包含未在 pubspec.yaml
檔案中宣告的資源。在這種情況下,對於要打包的圖片,應用程式必須在 pubspec.yaml
中指定包含哪些影象。例如,一個名為 fancy_backgrounds
的套件,可能包含以下檔案:
.../lib/backgrounds/background1.png
.../lib/backgrounds/background2.png
.../lib/backgrounds/background3.png
總而言之,要包含第一張影象,必須在 pubspec.yaml
的 assets
部分中宣告它:
flutter:
assets:
- packages/fancy_backgrounds/backgrounds/background1.png
lib/
是隱含的,所以它不應該包含在資源路徑中。
如果你正在開發 package,想要從 package 中載入資源,首先要在 pubspec.yaml
中定義:
flutter:
assets:
- assets/images/
在 package 中載入圖片,按以下方式:
return const AssetImage('packages/fancy_backgrounds/backgrounds/background1.png');
平台共享 assets
在不同平台讀取 Flutter assets,
Android 是透過 AssetManager
,iOS 是 NSBundle
。
在 Android 中載入 Flutter 資源檔案
在 Android 平台上,assets 透過 AssetManager
API 讀取。透過 PluginRegistry.Registrar
的 lookupKeyForAsset
方法,或者 FlutterView
的 getLookupKeyForAsset
方法來獲取檔案路徑,然後 AssetManager
的 openFd
根據檔案路徑得到檔案描述符。開發外掛時可以使用 PluginRegistry.Registrar
,而開發應用程式使用平台檢視時,FlutterView
是最好的選擇。
舉個例子,假設你在 pubspec.yaml 中這樣指定:
flutter:
assets:
- icons/heart.png
在你的 Flutter 應用程式對應以下結構。
.../pubspec.yaml
.../icons/heart.png
...etc.
想要在 Java 外掛中訪問 icons/heart.png
;
AssetManager assetManager = registrar.context().getAssets();
String key = registrar.lookupKeyForAsset("icons/heart.png");
AssetFileDescriptor fd = assetManager.openFd(key);
在 iOS 中載入 Flutter 資源檔案
在 iOS 平台上,assets 資源檔案透過 mainBundle
讀取。透過 pathForResource:ofType:
的 lookupKeyForAsset
或者 lookupKeyForAsset:fromPackage:
方法獲取檔案路徑,同樣,FlutterViewController
的 lookupKeyForAsset:
或者 lookupKeyForAsset:fromPackage:
方法也可以獲取檔案路徑。開發外掛時可以使用 FlutterPluginRegistrar
,而開發應用程式使用平台檢視時, FlutterViewController
是最好的選擇。
舉個例子,假設你的 Flutter 設定和上面一樣。
要在 Objective-C 外掛中訪問 icons/heart.png
:
NSString* key = [registrar lookupKeyForAsset:@"icons/heart.png"];
NSString* path = [[NSBundle mainBundle] pathForResource:key ofType:nil];
要在 Swift 應用程式中訪問 icons/heart.png
:
let key = controller.lookupKey(forAsset: "icons/heart.png")
let mainBundle = Bundle.main
let path = mainBundle.path(forResource: key, ofType: nil)
這有一個更完整的實例可以理解 Flutter 的應用:
video_player
plugin。
pub.dev 上的 ios_platform_images
plugin 將這些邏輯封裝成方便的類別。它允許編寫:
Objective-C:
[UIImage flutterImageWithName:@"icons/heart.png"];
Swift:
UIImage.flutterImageNamed("icons/heart.png")
在 Flutter 中載入 iOS 的圖片
當你在 iOS 應用程式中新增 Flutter 時,你可能希望在 Flutter 中使用 iOS 中的圖片。為了實現這一點,可以使用 pub.dev 上的 ios_platform_images
外掛。
平台 assets
某些場景可以直接在平台專案中使用 assets。以下是在 Flutter 框架載入並執行之前使用資源的兩種常見情況。
更新桌面圖示
更新你的 Flutter 應用程式啟動圖示,和原生 Android 或 iOS 應用程式中更新啟動圖示的方法相同。
Android
在 Flutter 專案的根目錄中,導向到 .../android/app/src/main/res
路徑。各種點陣圖資源檔案夾,比如 mipmap-hdpi
,已包含佔位符影象 ic_launcher.png
。只需按照 Android 開發者指南 中的說明,將其替換為所需的資源,並遵守每種螢幕解析度的建議圖示大小標準。
iOS
在你的 Flutter 專案的根目錄中,導向到 .../ios/Runner
路徑。該目錄中 Assets.xcassets/AppIcon.appiconset
已經包含佔位符圖片,只需將它們替換為適當大小的圖片,並且根據 iOS 開發指南,檔案名稱保持不變。
更新啟動圖
在 Flutter 框架載入時,Flutter 會使用原生平台機制繪製啟動頁。此啟動頁將持續到 Flutter 渲染應用程式的第一幀。
Android
將啟動螢幕「splash screen」新增到你的 Flutter 應用程式,請導向至 .../android/app/src/main
路徑。在 res/drawable/launch_background.xml
檔案中,透過使用
圖層清單 XML 來實現自定義啟動頁。現有樣板提供了一個範例,用於將圖片新增到白色啟動頁的中間(註解程式碼中)。你也可以取消註解使用 可繪製物件資源 來實現預期效果。
更多詳細訊息,請檢視 在 Android 應用中新增螢幕閃爍頁與啟動頁。
iOS
將圖片新增到啟動螢幕「splash screen」的中心,請導向至 .../ios/Runner
路徑。在 Assets.xcassets/LaunchImage.imageset
,拖入圖片,並命名為 LaunchImage.png
, LaunchImage@2x.png
,LaunchImage@3x.png
。如果你使用不同的檔案名,那你還必須更新同一目錄中的 Contents.json
檔案中對應的名稱。
你也可以透過開啟 .../ios/Runner.xcworkspace
,完全自定義 storyboard。在 Project Navigator 中導向到 Runner/Runner
,然後開啟 Assets.xcassets
拖入圖片,或者在 LaunchScreen.storyboard
中使用 Interface Builder 進行自定義。
更多詳細訊息,請檢視 在 iOS 應用中新增螢幕閃爍頁與啟動頁。