如何使用Lottie实现动画闪屏

本文介绍了如何使用Android(Kotlin)和iOS(Swift)在本地添加带有Lottie动画的动画闪屏。

用dart代码可以直接在Flutter中添加动画闪屏,但是,在Flutter实际绘制第一帧之前,Flutter应用程序在Android和iOS中作为FlutterActivity或FlutterViewController的启动方式会增加几秒钟。因此,在应用启动时,本机动画也会启动,从而带来更好的用户体验。

值得一提的是,添加静态图像为闪屏很容易,这在Flutter的官方文档中有详细记录,在这里你可以轻松将图像添加到Android的drawable和iOS资源中,然后在Android的的 styles.xml中和 iOS的 LaunchScreen.storyboard 中使用它们。但是,我找不到如何使用Lottie实现动画闪屏这类资源,而这就是我在本文中要解释的。

为什么选Lottie?

Lottie是一个支持多种平台(其中包括Android和iOS)的库,该平台可解析使用Bodymovin导出为json的Adobe After Effects动画,并进行本地渲染。这意味着动画是由设计人员创建的,开发人员很容易就能导出 json 文件。在本教程中,我将使用一个由LottieFiles创建的免费示例文件,这个链接上能找到,那我们现在就开始吧。

1_pb31XzMIs4Od021zU5g1Mw

创建一个新的flutter项目,需要以下几个步骤:

安卓

1.首先将Lottie依赖项添加到/ android / app /里的项目 build.gradle 文件中:(我还添加了约束布局依赖项)

dependencies {
   ...
   implementation "com.airbnb.android:lottie:3.5.0"
   implementation "com.android.support.constraint:constraint-layout:2.0.4"
   ...
}

2.在 AndroidManifest.xml 中,删除带有 io.flutter.embedding.android.SplashScreenDrawable 名称的元数据标签,用 NormalTheme 代替活动标签下的 LaunchTheme ,这样你的文件将如下所示;

<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>

因为不再需要 LaunchTheme 了,所以你可以从/android/app/res/values/styles.xml 中将其删除。

3.无论你是自己创建的文件还是从上面链接中下载的免费样本,你都要在/ android / app / res / values下创建一个 raw 目录,然后复制.json文件。在本教程中,将文件命名为 splash_screen.json

4.为了使用.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()
    }
}

如你所见,该视图正在放大 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项目目录

这就是Android的全部内容。只需运行该应用程序,即可在应用程序启动时看到动画屏幕

1_EDVg6zpUrwJ39ppvlN7nTA
动画启动画面-Android

iOS

让我们现在在iOS中添加启动屏幕。

1.导航到项目所在的目录,用xcode打开项目,单击ios文件夹,然后双击 Runner.xcworkspace

2.单击 Main.storyboard ,你将看到带有一个可视屏幕的布局编辑器。我们需要添加一个新的ViewController,作为 我们的 启动屏幕。你可以通过单击右上角的 + 符号来执行此操作,随后出现一个弹出窗口,搜索View Controller并将其拖动到编辑器,截屏如下;


添加一个新的视图控制器

3.完成第2步后,你会看到2个屏幕。选择新的视图控制器,并单击 attributes inspector 然后检查 is initial view controller


将视图控制器设置为初始视图控制器

4.我们需要将Lottie依赖项添加到/ ios / podFile;

pod 'lottie-ios'

文件将如下所示;

#platform :ios, '9.0' 
target 'Runner' do  
   use_frameworks!  
  
   pod 'lottie-ios' 
end

然后运行;(确保你在ios目录中,否则要在flutter项目的根目录中运行 cd ios

pod install

5.不管你是创建自己的文件还是从上面的链接下载了免费样本,都需将.json文件拖放到/ ios / Runner /下( 如有选项 ,选择“ 复制 ”选项),在本教程中,其名为 splash_screen.json

6.在已添加依赖项和splash_screen.json文件的情况下,我们可以创建我们的初始视图控制器,该控制器会处理显示动画,然后导航至Flutter的应用程序。在/ ios / Runner /中,创建一个新的swift文件,将其命名为 SplashViewController 。在类中编写任何内容之前,我们应该修改 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

7.完成后,现在我们可以准备 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 ,我们必须获取创建完的FlutterEngine的实例,并在AppDelegate.swift中运行。

let appDelegate = UIApplication.shared.delegate as! AppDelegate        let flutterEngine = appDelegate.flutterEngine
        
let flutterViewController = FlutterViewController(engine:    flutterEngine, nibName: nil, bundle: nil)

然后 present(completion:) 用于启动视图控制器。

  1. It’s time now to link the ViewController created at step 2 with the SplashViewController class. That can be done by clicking on Main.storyboard and selecting the new ViewController, then from identity inspector choose SplashViewController as the screenshot shows;

|60xauto

8.现在是时候将第2步创建的ViewController与SplashViewController类连接起来了。可以通过单击Main.storyboard并选择新的ViewController来进行,然后从identity inspector中选择SplashViewController ,如截图所示。


与SplashViewController链接

9.最后一步是设置Main.storyboard的主界面,而不是 LauncherScreen.storyboard 。要实现这一点,单击Runner,选择 General 选项卡,在 deployment info 下方,从下拉菜单中设置 Main interfaceMain ,如截图所示。

|28xauto
将主界面设置为MAIN

生成并运行app,你应该能够看到动画闪屏。

1_bdfeeBtOIHW_1A0MfdjnZQ

就是这样,你现在就拥有针对Android和iOS apps的动画闪屏了。

%E6%9C%AA%E5%91%BD%E5%90%8D_%E5%89%AF%E6%9C%AC

有关完整的源代码和演示应用程序;

如有任何疑问或有更好的方法可以解决此问题,欢迎评论。

原文作者 AbedElaziz Shehadeh
原文链接https://medium.com/swlh/native-splash-screen-in-flutter-using-lottie-121ce2b9b0a4

推荐阅读
作者信息
AgoraTechnicalTeam
TA 暂未填写个人简介
文章
131
相关专栏
本专栏仅用于分享音视频相关的技术文章,与其他开发者和 Agora 研发团队交流、分享行业前沿技术、资讯。发帖前,请参考「社区发帖指南」,方便您更好的展示所发表的文章和内容。