- 原文地址:Native Splash Screen in Flutter Using Lottie
- 原文作者:AbedElaziz Shehadeh
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:霜羽 Hoarfroster
- 校對者:zenblo、keepmovingljzy
我們當然可以直接使用 Dart 程式碼為 Flutter 應用程式新增動畫啟動效果,但是,Flutter 應用程式在 Android 和 iOS 中以 FlutterActivity 或 FlutterViewController 的形式啟動,會讓 Flutter 應用程式在實際繪製第一幀之前已經耗費了一段時間。因此,在應用啟動時設定啟動畫面將會帶來更好的使用者體驗。
值得一提的是,在 Flutter 的官方文件中我們可以輕鬆地將靜態影像新增為啟動頁,並且這個頁面上面有充足的文件資訊提供給我們使用。我們事實上只需將影像新增到 Android 的 drawable 資料夾中和 iOS 的資原始檔夾中,然後在 Android 的 styles.xml
和 iOS 的 LaunchScreen.storyboard
中使用它們即可。但是,在針對如何使用 Lottie 等其他庫實現應用程式啟動頁面動畫的功能,我並不能找到相關的參考資料,而這些就是我將在本文中講述的內容。
為什麼我們要使用 Lottie?
Lottie 是一個支援多平臺(包括 Android 與 iOS)的庫,用於通過 Bodymovin 解析 Adobe After Effects 匯出的 JSON 格式的動畫,並以本地方式呈現。這意味著動畫是由專業的設計人員設計的,並使用的是 JSON 檔案匯出,讓我們開發人員無需再額外付出什麼努力,輕輕鬆鬆完成動畫的渲染。在本教程中,我們將使用由 LottieFiles 建立的免費示例檔案,可以在這裡中找到該原檔案。讓我們開始我們的 Flutter + Lottie 之旅吧。
首先讓我們先建立一個新的 Flutter 專案,然後執行以下步驟:
Android
- 先新增 Lottie 依賴到你的專案的
app/build.gradle
檔案中(相對於 Flutter 應用程式則是android/app/build.gradle
檔案)(在這裡我也同樣新增了 Constraint Layout)
dependencies {
...
implementation "com.airbnb.android:lottie:3.5.0" # 當前版本 3.6.0
implementation "androidx.constraintlayout:constraintlayout:2.0.4"
# 譯者注:原文為 implementation "com.android.support.constraint:constraint-layout:2.0.4" 但 Lottie 2.8+ 只支援 AndroidX 專案
...
}
複製程式碼
- 在
AndroidManifest.xml
中刪去name
為 io.flutter.embedding.android.SplashScreenDrawable 的<meta-data>
標記並替換activity
標籤下面的LaunchTheme
為NormalTheme
,現在你的檔案是這樣的:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.abedelazizshe.flutter_lottie_splash_app">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="flutter_lottie_splash_app"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/NormalTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
複製程式碼
你可以在 /android/app/res/values/styles.xml
資料夾中刪除 LaunchTheme
的定義,因為你將不再需要它。
-
在
/android/app/res/values
資料夾下建立一個raw
目錄,並複製生成的.json
檔案(無論你是建立自己的檔案還是從上面的連結下載了免費示例)。 在本案例中,JSON 資料夾的名字應該是splash_screen.json
。 -
為了使用
.json
檔案並顯示動畫檢視,我們需要建立具有其佈局的啟動檢視類。 在/android/app/res
下,建立一個名為layout
的新目錄(如果不存在的話),然後建立一個名為splash_view.xml
的新的佈局資原始檔。 開啟這個 XML 檔案,修改檔案的程式碼為:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.airbnb.lottie.LottieAnimationView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:lottie_autoPlay="true"
app:lottie_rawRes="@raw/splash_screen"
app:lottie_loop="false"
app:lottie_speed="1.00" />
</androidx.constraintlayout.widget.ConstraintLayout>
複製程式碼
在這個示例中,我將動畫設定為自動播放,設定的播放速度為 1.0
,並且禁止迴圈播放功能。你可以根據需要使用不同的值。 最重要的部分是 app:lottie_rawRes
屬性,它定義了我們要使用在 raw
目錄中新增的 JSON 檔案。現在,我們需要建立啟動檢視的類。讓我們在 /android/app/src/main/kotlin/YOUR-PACKAGE-NAME
中來建立一個新的 Kotlin 類。將這個類命名為 SplashView
,然後修改它的內容為:
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import io.flutter.embedding.android.SplashScreen
class SplashView : SplashScreen {
override fun createSplashView(context: Context, savedInstanceState: Bundle?): View? =
LayoutInflater.from(context).inflate(R.layout.splash_view, null, false)
override fun transitionToFlutter(onTransitionComplete: Runnable) {
onTransitionComplete.run()
}
}
複製程式碼
如你所見,此檢視 Inflate 了 splash_view
佈局檔案。最後一步是告訴 MainActivity
我們的自定義啟動檢視。
5.轉到 /android/app/src/main/kotlin/YOUR-PACKAGE-NAME
資料夾,然後單擊 MainActivity.kt
。 FlutterActivity
提供了一種稱為 provideSplashScreen
的方法,修改程式碼為:
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.android.SplashScreen
class MainActivity: FlutterActivity() {
override fun provideSplashScreen(): SplashScreen? = SplashView()
}
複製程式碼
現在專案的目錄應該像這樣:
這就是 Android 下 Lottie 構建 Splash 啟動頁的方法,只需要跑一下這個應用程式然後你就能夠看到應用程式啟動時候的動畫了。
iOS
讓我們在 iOS 中新增啟動頁:
- 開啟專案所在的目錄,單擊 ios 資料夾,然後雙擊
Runner.xcworkspace
開啟你的專案。
2.單擊 Main.storyboard
,你將看到帶有一個螢幕的佈局編輯器。 我們需要新增一個新的 ViewController
,這將是我們的啟動頁(你可以通過單擊右上角的 +
號來做到這一點。點選之後,螢幕中將彈出一個視窗。我們在輸入框處輸入 View Controller 搜尋並將這個控制元件拖動到編輯器中即可),如以下螢幕快照所示:
- 完成了第二步之後,你會看到兩個螢幕。選擇新的 View Controller 然後點選
attributes inspector
,然後再點選is initial view controller
.
- 我們需要在
ios/Podfile
檔案中新增 Lottie 依賴;
pod 'lottie-ios'
複製程式碼
這個檔案中現在應該是這樣的:(編者注:可能你已經修改了一部分設定了,這裡只是一個案例)
#platform :ios, '9.0'
target 'Runner' do
use_frameworks!
pod 'lottie-ios'
end
複製程式碼
然後執行這個應用程式(確保命令列當前在 ios 目錄中。如果不是,那麼就使用 cd
命令將你的目錄移動到 ios 目錄中)
pod install
複製程式碼
- 使用 Xcode 將你的生成的
.json
檔案拖到中的根目錄中(請選擇Copy items if needed
選項),這個檔案可能是你自己建立的檔案,也有可能是你從上面的連結下載了免費樣本。在本案例中它的名字是splash_screen.json
。
6.在已經新增了依賴項和 splash_screen.json
檔案的情況下,我們可以建立我們的初始檢視控制器,該控制器將處理顯示的動畫。開啟你的 ios 專案,在專案根目錄處(相對於 Flutter 根目錄:/ios/Runner)建立一個新的名為 SplashViewController
的 Swift 檔案。在類中編寫任何內容之前,我們先來修改一下 AppDelegate.swift
以建立 FlutterEngine
。 如果你跳過了這個步驟,則動畫啟動畫面的動畫播放完了以後不能跳轉至 FlutterViewController
。
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
lazy var flutterEngine = FlutterEngine(name: "MyApp")
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Runs the default Dart entrypoint with a default Flutter route.
flutterEngine.run()
// Used to connect plugins (only if you have plugins with iOS platform code).
GeneratedPluginRegistrant.register(with: self.flutterEngine)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
複製程式碼
在這裡我們建立了一個名為 MyApp
的 FlutterEngine
(你可以自己決定它的名稱),然後在 application
的 didFinishLaunchingWithOptions
中執行了這個引擎並在引擎中註冊了外掛。需要注意的是預設程式碼是 GeneratePluginRegistrant.register(with:self)
,請確保它已向 self.flutterEngine
註冊。
- 做完了這些,現在我們可以準備
SplashViewController
以顯示動畫。導航到Flutter
的 View Controller 處,修改程式碼為:
import UIKit
import Lottie
public class SplashViewController: UIViewController {
private var animationView: AnimationView?
public override func viewDidAppear(_ animated: Bool) {
animationView = .init(name: "splash_screen")
animationView!.frame = view.bounds
animationView!.contentMode = .scaleAspectFit
animationView!.loopMode = .playOnce
animationView!.animationSpeed = 1.00
view.addSubview(animationView!)
animationView!.play{ (finished) in
self.startFlutterApp()
}
}
func startFlutterApp() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let flutterEngine = appDelegate.flutterEngine
let flutterViewController =
FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
flutterViewController.modalPresentationStyle = .custom
flutterViewController.modalTransitionStyle = .crossDissolve
present(flutterViewController, animated: true, completion: nil)
}
}
複製程式碼
在 viewDidAppear
中,我們使用新增的 splash_screen.json
檔案初始化動畫檢視。你可以修改諸如 loopMode
、animationSpeed
等播放設定。在動畫播放結束後,我們將啟動我們的 Flutter 應用程式。
為了獲取 FlutterViewController
,我們必須獲取我們建立並在 AppDelegate.swift
執行的 FlutterEngine
的例項。
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let flutterEngine = appDelegate.flutterEngine
let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
複製程式碼
然後使用 present(completion :)
啟動檢視控制器。
- 現在是時候將第 2 步建立的
ViewController
與SplashViewController
類相連結了。單擊Main.storyboard
並選擇新的ViewController
,然後從identity inspector
中選擇SplashViewController
,如螢幕快照所示:
- 最後一步是設定
Main.storyboard
的主介面,替換掉LauncherScreen.storyboard
。單擊 Runner,選擇General
選項卡,在deployment info
下,從下拉選單中將Main interface
設定為 Main,如螢幕快照所示:
生成並執行該應用程式,你應該能夠看到動畫的啟動頁了:
就是這樣,你現在已經生成了針對 Android 和 iOS 應用程式的動畫啟動頁。有關完整的原始碼和演示應用程式可以在這裡獲取到:
AbedElazizShe/flutter_lottie_splash_app
如果你有任何疑問,或者有更好的方法可以解決此問題,請記得發表評論嗷。
- 本文正在參與「掘金 2021 春招闖關活動」, 點選檢視 活動詳情
如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。