除了Angular 10 支持之外,我们还在 NativeScript 中引入了对 APP_INITIALIZER
的正确支持,以及我们想要在此展示的新启动选项。新选项包括:async
、launchView
和 backgroundColor
,这些选项可以在引导应用程序时指定。
首先让我们回顾一下如何使用 Angular 的 APP_INITIALIZER
在应用程序启动期间处理异步任务。
async
启动选项// can be used in any app.module:
import { NgModule, APP_INITIALIZER } from '@angular/core';
export function asyncBoot(): Function {
return (): Promise<any> => new Promise(resolve => {
setTimeout(() => {
resolve();
}, 5000);
})
}
@NgModule({
imports: [NativeScriptModule],
declarations: [AppComponent],
bootstrap: [AppComponent],
providers: [
{
provide: APP_INITIALIZER,
useFactory: asyncBoot,
multi: true
},
]
})
export class AppModule {}
// when using async app initialization, be sure to set the `async` boot option in `main.ts` like this:
platformNativeScriptDynamic({
async: true
}).bootstrapModule(AppModule);
例如,如果需要,可以在 asyncBoot
工厂函数中注入 HttpClient
来处理各种 API 调用,然后再引导应用程序。
您可以使用标准的 NativeScript API 创建多种动画启动屏幕,但以下是动画 GIF 中看到的精确动画启动屏幕以及如何使用新的 launchView
启动选项。
import {
platformNativeScriptDynamic,
AppLaunchView,
} from "@nativescript/angular";
import { GridLayout } from "@nativescript/core";
import { AppModule } from "./app/app.module";
class LaunchAnimation extends GridLayout implements AppLaunchView {
circle: GridLayout;
finished = false;
complete: () => void;
constructor() {
super();
this.backgroundColor = "#4caef7";
this.className = "w-full h-full";
// construct any creative animation
this.circle = new GridLayout();
this.circle.width = 30;
this.circle.height = 30;
this.circle.borderRadius = 15;
this.circle.horizontalAlignment = "center";
this.circle.verticalAlignment = "middle";
this.circle.backgroundColor = "#fff";
this.addChild(this.circle);
}
async startAnimation() {
await this.circle.animate({
scale: { x: 2, y: 2 },
duration: 800,
});
await this.circle.animate({
scale: { x: 1, y: 1 },
duration: 800,
});
if (this.finished) {
await this.circle.animate({
scale: { x: 30, y: 30 },
duration: 400,
});
this.fadeOut();
} else {
// keep looping
this.startAnimation();
}
}
cleanup() {
return new Promise((resolve) => {
this.complete = resolve;
this.finished = true;
});
}
async fadeOut() {
await this.animate({
opacity: 0,
duration: 400,
});
this.complete();
}
}
platformNativeScriptDynamic({
launchView: new LaunchAnimation()
}).bootstrapModule(AppModule);
backgroundColor
在仅使用 async
时很有用如果您一直希望在应用程序首次启动时更好地控制其背景颜色,则可以像这样设置 backgroundColor
。
platformNativeScriptDynamic({
backgroundColor: 'purple'
}).bootstrapModule(AppModule);
这在与异步 APP_INITIALIZER
一起使用时特别有用,因为您可能不希望用户在应用程序异步准备启动时停留在空白白屏上(这可能在启动屏幕消失后发生,并且当使用 Angular 的 APP_INITIALIZER
令牌进行异步处理时,您的应用程序可能仍在异步初始化)。
新的 launchView
选项还可以与Lottie结合使用,从而为动画提供更大的灵活性。如果您之前从未听说过 Lottie,Lottie 是 Airbnb 创建的一个动画库,它允许您使用从 Adobe After Effects 导出的 JSON 文件创建精美的动画。我们可以使用 Brad Martin 的 nativescript-lottie 插件在我们的 Nativescript 应用程序中使用它。该插件还有一些示例效果,我将在本文中使用它们。这里 是一个链接,如果您想尝试一下。
我们首先需要使用以下命令将 nativescript-lottie
插件添加到我们的项目中,并在我们将添加动画代码的 main.ts
中导入它。
ns plugin add nativescript-lottie
我们将在此扩展 GridLayout
,以便我们可以轻松地分层和定位元素。首先让我们为我们将要使用的每个方法创建一个存根,以及每个方法将执行的操作。
class LaunchAnimation extends GridLayout implements AppLaunchView {
constructor() {
super();
// define our layout, containers, and UI elements
}
startAnimation(): void {
// start and stop animation
}
cleanup(): Promise<any> {
// set flag to stop animation
// returns a promise to provide further control over resolving when your animation is completely finished
}
}
LottieView
的 src
属性指向一个 lottie json 文件,该文件位于 iOS 的 app/App_Resources/iOS
和 Android 的 app/App_Resources/Android/src/main/assets
中。
import { LottieView } from 'nativescript-lottie';
class LaunchAnimation extends GridLayout implements AppLaunchView {
lottieView: LottieView;
complete: () => void;
constructor() {
super();
this.backgroundColor = '#4caef7';
this.className = 'w-full h-full';
// setup lottie
this.lottieView = new LottieView();
this.lottieView.height = 300;
this.lottieView.width = 300;
this.lottieView.src = 'lottie/pinjump.json';
// add lottieview to container
this.addChild(this.lottieView);
}
}
如前所述,我们将使用 startAnimation()
方法播放动画,并使用 cleanup()
方法触发动画停止。我们还将添加一个 fadeOut()
方法来从动画过渡到应用程序的第一页。
为了优雅地结束动画,我们将添加一个 finished
标志,当调用 cleanup()
时,该标志将设置为 true
,表示动画在完成当前循环后停止。然后,此标志在我们的 startAnimation()
方法中使用,在该方法中,我们让 lottieView.completionBlock
检查此标志,如果 finished
为假,则再次调用 startAnimation()
,重新播放动画,或者如果 finished
为真,则调用 fadeOut()
,结束动画,然后淡出 LaunchAnimation 并过渡到应用程序的主页。
class LaunchAnimation extends GridLayout implements AppLaunchView {
lottieView: LottieView;
finished = false;
complete: () => void;
constructor() {
super();
this.backgroundColor = '#4caef7';
this.className = 'w-full h-full';
// setup lottie
this.lottieView = new LottieView();
this.lottieView.height = 300;
this.lottieView.width = 300;
this.lottieView.src = 'lottie/pinjump.json';
// add lottieview to container
this.addChild(this.lottieView);
}
startAnimation() {
this.lottieView.completionBlock = () => this.finished ? this.fadeOut() : this.startAnimation();
this.lottieView.playAnimation();
}
cleanup() {
return new Promise(resolve => {
this.complete = resolve;
this.finished = true;
});
}
async fadeOut() {
await this.animate({
opacity: 0,
duration: 400,
});
this.complete();
}
}
现在我们已经设置了 LaunchAnimation
,可以在引导时定义我们的 launchView
选项。
platformNativeScriptDynamic({
launchView: new LaunchAnimation(),
}).bootstrapModule(AppModule);