Angular + Nativescript 代码共享项目删除操作栏
Angular + Nativescript Code Sharing Project Remove Action Bar
我的项目正在使用 Angular + Nativescript 代码共享项目为 Android 和 IOS.
的 Web 和移动设备构建
问题是试图删除整个应用程序的操作栏。我已经阅读了一些关于这个问题的帖子,但是 none 的解决方案似乎有效,或者至少最终不是一个很好的解决方案。
我尝试添加 <Page actionBarHidden="true"></page>
但这在 app.component
或其他包含路由的组件中根本不起作用,例如带有路由 [=17= 的 home.component
].如:
<Page actionBarHidden="true">
<StackLayout orientation="vertical">
<Image src="res://buy" stretch="none" horizontalAlignment="center"></Image>
</StackLayout>
</Page>
我还尝试了一种专门针对 android 的方法,看看我是否可以通过 AndroidManifest.xml
文件解决这个问题,就像我通过更新 Android 制作原生 Android 应用程序一样。 =47=] manifest 带走操作栏。为了进行完整性测试,我还尝试通过 styles.xml
使用它,例如:
<style name="AppThemeNoActionBar" parent="AppTheme">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
在这些失败的尝试之后,我尝试了以下涉及 Page
的其他人推荐的代码,例如:
import { Page } from 'tns-core-modules/ui/page';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
ngOnInit() {
this.page.actionBarHidden = true;
}
}
此方法的问题是要使此解决方案起作用,我需要为每个具有路由的组件创建一个 tns
文件,只是为了调用它来完全删除应用程序栏,因为每个页面似乎都处理他们自己的应用程序栏。现在这并不是真正可大规模维护的,而且它迫使我为所有具有路由的组件创建一个 tns
文件。
最后,我看到了一个示例,其中我们有一个服务具有针对 this.page.actionBarHidden
和 rootFrame.actionBarVisibility = 'never'
的逻辑,您可以在 component.ts
文件中调用它而无需创建一个 component.tns.ts
文件,但是现在的问题是您需要创建一个具有要调用的空函数的常规服务,为实际逻辑创建该服务的 tns
文件,以及必须在每个有路由的组件中调用它。
如您所见,有些解决方案根本行不通,而另一些则需要大量额外代码和可维护性,尤其是随着应用程序的增长,它们并不是非常理想的解决方案。
我会继续研究这个问题,我相信必须有一个干净的解决方案。
经过更多研究和测试后,我找到了一个按预期工作的解决方案。以及我将解释为什么其他一些方法没有按预期工作的原因。
首先是 <Page actionBarHidden="true">
。根据我的研究和测试,这仅在您专门为 nativescript 构建而不是作为 Angular + Nativescript 代码共享项目时才有效。这样做的原因是,当我们使用 Angular 进行 Web 开发时,我们正在使用 <router-outlet></router-outlet>
,对于 Angular 的新手,这会处理更改应用程序内的路由并根据路由显示正确的组件.
现在,当我们开始编写 Nativescript 时,我们希望尽可能多地重用代码,包括我们的路由。在这种情况下,我们最终会在 app.component.tns.html
文件中使用 <page-router-outlet></page-router-outlet>
。很像 Angular 当我们改变路线时,这将控制基于路线的正确组件的显示。
问题的发生是因为 <page-router-outlet></page-router-outlet>
自动为我们创建了一个 <Page></Page>
。因此,无论是 app.component.tns.html
还是 home.component.tns.html
,将一个放在我们的模板中都不会起作用,因为它已经有了一个我们无法在我们的 html 文件中轻松引用它。
对于尝试通过 App_Resources
文件夹中的 android 清单执行此操作的问题,我也没有成功。我相信是因为当我们使用 <page-router-outlet></page-router-outlet>
Nativescript 时会在内部更改清单以反映并默认强制我们使用操作栏。我试过用几种不同的方式设置它,不管它是一样的。我能够通过 Platform
文件夹让它工作,但是我不推荐这样做,因为有时我们需要删除和添加平台,这可能会导致我们忘记或不得不继续实施相同的解决方案,浪费宝贵的开发时间。
下一期使用this.page.actionBarHidden = true;
本期与第一期属于同一类别。当您尝试在 app.component.tns.ts
文件中执行此操作时,它永远不会单独使用该命令,因为我们正在使用 <page-router-outlet></page-router-outlet>
。本质上 AppComponent
根本看不到该页面,因为它不属于它。当应用程序加载时,如果您的第一个默认路由指向 home 组件,那么您需要在 Home 组件中使用 this.page.actionBarHidden
。但是,为了在 web 中不失败,您需要为每个组件创建一个 tns 文件,该文件有一个路由以在其中专门包含该逻辑,而这在可维护性方面是不切实际的。
对于最后一期,我们不应该重复代码。在这种情况下,将在每个 component.tns.ts
文件上调用该函数,只是为了删除我们想要在应用程序范围内使用的内容。以及创建我们不需要的额外 tns files
和管理另一项服务 运行 一段仅适用于 nativescript 的代码。
解决方案
这是我能找到的最简单的解决方案,它允许在一个位置处理操作栏,以便随时轻松更改。解决方法是使用Angular的Router
。我们在 ngOnInit
中所做的是订阅路由器的事件。然后当 Router 事件触发时,我们检查并验证它是否是导航到被路由到的组件的结束。在检查通过的这个阶段,应用程序已经导航到路由,现在我们可以安全地获取对 Frame
或 Page
的引用并删除操作栏。
Nativescript 有一个名为 topMost()
的函数,它允许我们获取对显示的 Frame
或 Page
的引用。根据他们的代码定义:获取帧堆栈中最顶层的帧。一个应用程序通常会有一个框架实例。多个框架处理嵌套(分层)导航场景。
因此,使用它我们可以轻松获得对当前正在显示的帧的 Page
的引用。现在我们已经显示了框架,我们只需将 actionBarVisibility
设置为 false;
import { Component } from '@angular/core';
import { Page } from 'tns-core-modules/ui/page';
import { Router, NavigationEnd } from '@angular/router';
import { topmost } from 'tns-core-modules/ui/frame/frame';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
constructor(private _Router: Router, private page: Page) {
}
ngOnInit(): void {
this._Router.events.subscribe((ev) => {
if (ev instanceof NavigationEnd) {
const rootFrame = topmost();
rootFrame.actionBarVisibility = 'never';
}
});
}
}
您可以简单地在您的 page-router-outlet
上将 actionBarVisibility
设置为 never
。
<page-router-outlet actionBarVisibility="never"></page-router-outlet>
我的项目正在使用 Angular + Nativescript 代码共享项目为 Android 和 IOS.
的 Web 和移动设备构建问题是试图删除整个应用程序的操作栏。我已经阅读了一些关于这个问题的帖子,但是 none 的解决方案似乎有效,或者至少最终不是一个很好的解决方案。
我尝试添加 <Page actionBarHidden="true"></page>
但这在 app.component
或其他包含路由的组件中根本不起作用,例如带有路由 [=17= 的 home.component
].如:
<Page actionBarHidden="true">
<StackLayout orientation="vertical">
<Image src="res://buy" stretch="none" horizontalAlignment="center"></Image>
</StackLayout>
</Page>
我还尝试了一种专门针对 android 的方法,看看我是否可以通过 AndroidManifest.xml
文件解决这个问题,就像我通过更新 Android 制作原生 Android 应用程序一样。 =47=] manifest 带走操作栏。为了进行完整性测试,我还尝试通过 styles.xml
使用它,例如:
<style name="AppThemeNoActionBar" parent="AppTheme">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
在这些失败的尝试之后,我尝试了以下涉及 Page
的其他人推荐的代码,例如:
import { Page } from 'tns-core-modules/ui/page';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
ngOnInit() {
this.page.actionBarHidden = true;
}
}
此方法的问题是要使此解决方案起作用,我需要为每个具有路由的组件创建一个 tns
文件,只是为了调用它来完全删除应用程序栏,因为每个页面似乎都处理他们自己的应用程序栏。现在这并不是真正可大规模维护的,而且它迫使我为所有具有路由的组件创建一个 tns
文件。
最后,我看到了一个示例,其中我们有一个服务具有针对 this.page.actionBarHidden
和 rootFrame.actionBarVisibility = 'never'
的逻辑,您可以在 component.ts
文件中调用它而无需创建一个 component.tns.ts
文件,但是现在的问题是您需要创建一个具有要调用的空函数的常规服务,为实际逻辑创建该服务的 tns
文件,以及必须在每个有路由的组件中调用它。
如您所见,有些解决方案根本行不通,而另一些则需要大量额外代码和可维护性,尤其是随着应用程序的增长,它们并不是非常理想的解决方案。
我会继续研究这个问题,我相信必须有一个干净的解决方案。
经过更多研究和测试后,我找到了一个按预期工作的解决方案。以及我将解释为什么其他一些方法没有按预期工作的原因。
首先是 <Page actionBarHidden="true">
。根据我的研究和测试,这仅在您专门为 nativescript 构建而不是作为 Angular + Nativescript 代码共享项目时才有效。这样做的原因是,当我们使用 Angular 进行 Web 开发时,我们正在使用 <router-outlet></router-outlet>
,对于 Angular 的新手,这会处理更改应用程序内的路由并根据路由显示正确的组件.
现在,当我们开始编写 Nativescript 时,我们希望尽可能多地重用代码,包括我们的路由。在这种情况下,我们最终会在 app.component.tns.html
文件中使用 <page-router-outlet></page-router-outlet>
。很像 Angular 当我们改变路线时,这将控制基于路线的正确组件的显示。
问题的发生是因为 <page-router-outlet></page-router-outlet>
自动为我们创建了一个 <Page></Page>
。因此,无论是 app.component.tns.html
还是 home.component.tns.html
,将一个放在我们的模板中都不会起作用,因为它已经有了一个我们无法在我们的 html 文件中轻松引用它。
对于尝试通过 App_Resources
文件夹中的 android 清单执行此操作的问题,我也没有成功。我相信是因为当我们使用 <page-router-outlet></page-router-outlet>
Nativescript 时会在内部更改清单以反映并默认强制我们使用操作栏。我试过用几种不同的方式设置它,不管它是一样的。我能够通过 Platform
文件夹让它工作,但是我不推荐这样做,因为有时我们需要删除和添加平台,这可能会导致我们忘记或不得不继续实施相同的解决方案,浪费宝贵的开发时间。
下一期使用this.page.actionBarHidden = true;
本期与第一期属于同一类别。当您尝试在 app.component.tns.ts
文件中执行此操作时,它永远不会单独使用该命令,因为我们正在使用 <page-router-outlet></page-router-outlet>
。本质上 AppComponent
根本看不到该页面,因为它不属于它。当应用程序加载时,如果您的第一个默认路由指向 home 组件,那么您需要在 Home 组件中使用 this.page.actionBarHidden
。但是,为了在 web 中不失败,您需要为每个组件创建一个 tns 文件,该文件有一个路由以在其中专门包含该逻辑,而这在可维护性方面是不切实际的。
对于最后一期,我们不应该重复代码。在这种情况下,将在每个 component.tns.ts
文件上调用该函数,只是为了删除我们想要在应用程序范围内使用的内容。以及创建我们不需要的额外 tns files
和管理另一项服务 运行 一段仅适用于 nativescript 的代码。
解决方案
这是我能找到的最简单的解决方案,它允许在一个位置处理操作栏,以便随时轻松更改。解决方法是使用Angular的Router
。我们在 ngOnInit
中所做的是订阅路由器的事件。然后当 Router 事件触发时,我们检查并验证它是否是导航到被路由到的组件的结束。在检查通过的这个阶段,应用程序已经导航到路由,现在我们可以安全地获取对 Frame
或 Page
的引用并删除操作栏。
Nativescript 有一个名为 topMost()
的函数,它允许我们获取对显示的 Frame
或 Page
的引用。根据他们的代码定义:获取帧堆栈中最顶层的帧。一个应用程序通常会有一个框架实例。多个框架处理嵌套(分层)导航场景。
因此,使用它我们可以轻松获得对当前正在显示的帧的 Page
的引用。现在我们已经显示了框架,我们只需将 actionBarVisibility
设置为 false;
import { Component } from '@angular/core';
import { Page } from 'tns-core-modules/ui/page';
import { Router, NavigationEnd } from '@angular/router';
import { topmost } from 'tns-core-modules/ui/frame/frame';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
constructor(private _Router: Router, private page: Page) {
}
ngOnInit(): void {
this._Router.events.subscribe((ev) => {
if (ev instanceof NavigationEnd) {
const rootFrame = topmost();
rootFrame.actionBarVisibility = 'never';
}
});
}
}
您可以简单地在您的 page-router-outlet
上将 actionBarVisibility
设置为 never
。
<page-router-outlet actionBarVisibility="never"></page-router-outlet>