在 NativeScript 应用程序中实现对话框的方法有很多。 NativeScript 对话框模块 允许您使用内置 API 显示各种对话框,非常适合简单的用例。
NativeScript 对话框模块示例。 在 NativeScript Playground 中尝试此示例
另一方面,您还可以创建完全模态页面的对话框,并带有原生过渡效果。当您希望完全控制对话框的外观和工作方式时,这些对话框非常有用。
NativeScript 中模态页面示例。 在 NativeScript Playground 中尝试此示例
但是,根据我的经验,有时您需要一个可以自定义样式的简单对话框,而无需创建整个页面。基本上,您想要类似这样的东西。
在本文中,我将引导您完成创建上面所示简单对话框的过程。我将使用 Angular 进行说明,但无论您使用的是 Angular、Vue.js 还是 NativeScript Core,这些技术都大致相同。
以下是在高级别上构建此对话框的标记。
<GridLayout class="page">
<GridLayout class="content">
<StackLayout>
<!-- Page content goes here -->
</StackLayout>
</GridLayout>
<AbsoluteLayout class="dialog-wrapper">
<StackLayout class="dialog">
<!-- Dialog content goes here -->
</StackLayout>
</AbsoluteLayout>
</GridLayout>
首先,您有一个外部 <GridLayout>
,它包含整个页面。如果您使用的是 Angular,则这需要是页面组件的根元素,如果您没有使用 Angular,则这需要是根 <Page>
元素的唯一子元素。
您的页面有两个子元素:一个 <GridLayout>
,它将包含应用程序的内容,以及一个 <AbsoluteLayout>
,它将充当对话框的容器。这里的想法是,您将像往常一样编写内容,并在应用程序中根据需要显示和隐藏对话框。为了做到这一点,让我们编写一些 TypeScript 和 CSS。
在您的代码中,您需要创建一个属性来跟踪对话框是否打开,以及一些用于操作对话框状态的方法。如果您使用的是 Angular,则代码如下所示。
import { Component } from "@angular/core";
@Component({
selector: "Home",
moduleId: module.id,
templateUrl: "./home.component.html",
styleUrls: ['./home.component.css']
})
export class HomeComponent {
dialogOpen = false;
showDialog() {
this.dialogOpen = true;
}
closeDialog() {
this.dialogOpen = false;
}
}
dialogOpen
属性顾名思义,跟踪对话框当前是否打开。您将其设置为默认值 false
,因为您通常不希望对话框在页面加载时显示。
现在您已经有了属性,下一步是将其应用于您的标记。一种方法是使用以下标记。
<GridLayout class="page" [class.dialogOpen]="dialogOpen">
<GridLayout class="content">
<StackLayout>
<Button class="btn btn-primary" text="Show Dialog" (tap)="showDialog()"></Button>
</StackLayout>
</GridLayout>
<AbsoluteLayout class="dialog-wrapper">
<StackLayout class="dialog">
<Label textWrap="true" text="Are you sure you want to continue?"></Label>
<Button class="btn btn-primary" text="Yes"></Button>
<Button class="btn" text="No" (tap)="closeDialog()"></Button>
</StackLayout>
</AbsoluteLayout>
</GridLayout>
此标记中有一些更改以使用您的新属性。首先,您添加了两个 tap
事件处理程序,一个是您主要内容中的一个按钮,用于显示对话框,另一个是在对话框的取消按钮上,用于关闭对话框。
其次,您使用 Angular 的 []
语法有条件地将 dialogOpen
CSS 类名称应用于您的主要页面元素。此类名称将作为您需要使对话框表现得像对话框的钩子。要了解其工作原理,让我们看看您需要使这一切都结合在一起的 CSS。
信不信由你,您已经拥有使此示例工作所需的所有标记和代码,因为此示例的真正魔力发生在 CSS 中。以下是最少所需的 CSS 代码。
.dialogOpen .content {
opacity: 0.2;
}
.dialogOpen .dialog-wrapper {
visibility: visible;
}
.dialog-wrapper {
visibility: collapse;
}
.dialog {
border-width: 1 0 1 0;
border-color: black;
width: 100%;
margin-top: 100;
}
默认情况下,对话框包装器元素的 visibility
设置为 collapse
,这会将对话框隐藏在用户面前。
但是,当 dialogOpen
类被应用时,.dialogOpen .dialog-wrapper
选择器现在被应用,对话框包装器的 visibility
设置为 visible
,这会将对话框显示给用户。此外,.dialogOpen .content
选择器现在被应用,并将主要内容的 opacity
更改为 0.2
,这使其略微变暗,有助于将焦点放在对话框内容上。
将所有这些结合在一起,您应该有一个看起来有点像这样的对话框。
您可以通过多种方式改进这个简单的设计。首先,您可以添加一些动画,为对话框提供一个不错的淡入效果。该代码如下所示。
@keyframes show {
from { opacity: 0; }
to { opacity: 1; }
}
.dialogOpen .content {
opacity: 0.2;
}
.dialogOpen .dialog-wrapper {
visibility: visible;
animation-name: show;
animation-duration: 0.3s;
animation-fill-mode: forwards;
}
.dialog-wrapper {
visibility: collapse;
opacity: 0;
}
.dialog {
border-width: 1 0 1 0;
border-color: black;
width: 100%;
margin-top: 100;
}
现在,当您设置 dialogOpen
类名称时,show
CSS 动画将在 0.3 秒内将对话框包装器的透明度从 0
更改为 1
。结果是一个不错的淡入效果,看起来像这样。
此时,您可能需要编写一些 CSS 来清理此 UI 中的间距,具体取决于您想要在对话框中显示的内容。您可以参考本文末尾列出的完整代码示例,查找如何执行此操作的一个示例。
在我离开之前,还有一个提示需要提一下。为了讨论,让我们回到此示例的基本标记。
<GridLayout class="page">
<GridLayout class="content">
<StackLayout>
<!-- Page content goes here -->
</StackLayout>
</GridLayout>
<AbsoluteLayout class="dialog-wrapper">
<StackLayout class="dialog">
<!-- Dialog content goes here -->
</StackLayout>
</AbsoluteLayout>
</GridLayout>
重点关注对话框包装器。因为对话框包装器是父页面的子元素,所以它继承了页面的尺寸,即包装器占据与页面相同的尺寸。这是设计使然,因为这意味着当对话框打开时,用户无法点击对话框后面的元素。本质上,包装器将此对话框变成了一个模态对话框。
但是,有一个例外。虽然包装器阻止了主页面被点击,但它的尺寸不会扩展到页面的 <ActionBar>
之上。因此,如果您的页面使用了 <ActionBar>
,用户将能够在对话框打开时与您放入其中的任何控件进行交互。
例如,假设您的应用程序中有一个 <ActionItem>
执行共享操作。类似于这样。
<ActionItem text="Share" (tap)="share()"></ActionItem>
import { Component } from "@angular/core";
@Component({
...
})
export class HomeComponent {
dialogOpen = false;
share() {
// Sharing code here
}
showDialog() { ... }
closeDialog() { ... }
}
在此示例中,用户可以在对话框打开时执行共享操作。这可能适合您的应用程序和您的场景。但是,如果不是,最简单的阻止操作方法是使用简单的 if
检查。例如,请注意以下代码中 if (this.dialogOpen)
的使用。
import { Component } from "@angular/core";
@Component({
...
})
export class HomeComponent {
dialogOpen = false;
share() {
if (this.dialogOpen) {
return;
}
// Sharing code here
}
showDialog() { ... }
closeDialog() { ... }
}
最终,您选择如何配置此示例取决于您应用程序的需求。请随时逐字复制此方法,或根据需要自定义此结构。
此示例的完善版本可用于 Angular、Vue.js 和 NativeScript Core,使用以下链接。请随意使用它们,如果您想出任何有趣的自定义功能,请在下面的评论中列出它们。
提示 此简单对话框只是 NativeScript 市场 中免费提供的大量示例之一。查看 示例的完整列表,甚至可以 贡献您自己的示例 😉