返回博客首页
← 所有文章

选项卡和底部导航 - NativeScript 的两个新组件

2019年9月26日 — 作者:Martin Yankov

在 NativeScript 6 中,我们在核心模块套件中引入了两个新的选项卡导航组件。它们被称为BottomNavigationTabs,旨在成为现有TabView组件的新替代方案,并且更加完善。现在,随着 6.1 版本的发布,它们终于脱离了测试阶段。

TabView Tabs Bottomnavigation Schema

一段时间前,我们发现TabView是我们报告问题最多的组件之一。鉴于该组件对整个应用程序导航的重要性,我们希望解决这个问题。问题范围从错误和使用困难到不支持的场景和限制。逐一解决这些问题效果不佳,我们采取了一种更全面的方法来找出问题所在。最终,我们决定进行完全重新设计,其中包括一种新的标记、样式和自定义方法。我们还从 Material Design 中汲取灵感,按功能分离组件,因此,我们有两个组件代替了TabViewBottomNavigationTabs

这两个新组件要好得多,以至于你应该完全忘记TabView。让我们看看原因。

提示:务必查看结尾处的自定义选项卡栏,以获得最大的酷炫体验。

城镇中的新组件

首先,我必须解释为什么我们决定使用两个单独的组件。BottomNavigationTabs组件按功能分离。正如我提到的,我们大量借鉴了 Material Design,因此你可以查看关于底部导航选项卡用法的文章,以获取一些关于设计方面的解释和示例。下表显示了这两个组件之间的行为差异

选项卡 底部导航
语义 中级导航 高级导航
用法 具有共同功能的无限选项卡 3 到 5 个具有不同功能的选项卡
过渡 滑动过渡 无过渡
手势 滑动手势 无手势
预加载 至少一侧 无预加载
位置 顶部/底部 底部


如你所见,这两个组件具有不同的行为,并且都有其用例。对于高级导航(其中单独的选项卡没有共享上下文),请使用BottomNavigation。当你希望创建一个类似于分页器的东西来浏览具有相同上下文的项目时,请使用Tabs组件。TabView组件的问题之一是它试图以一种奇怪的方式组合这两组行为 - 对于 Android,它实际上具有Tabs行为,而对于 iOS,它则具有BottomNavigation行为。从技术上讲,它提供了带有选项卡的导航,但实际上它很难使用和理解,而且也很难维护。

拥有两个组件的另一个好处是,你现在可以将它们组合在一起 - 在顶部使用Tabs,在底部使用BottomNavigation。这在以前是不可能的或非常难以实现的。

Tabs and BottomNavigation Combination

查看带有选项卡和底部导航组合的 Playground 示例

如你所见,这里有一些样式。让我们看看现在是如何完成的。

一切都是关于标记的

新组件还附带了新的标记。事实证明,标记对于 CSS 样式非常重要。为了充分利用它,我们必须为每个你想要设置样式的可见单元创建组件表示。BottomNavigationTabs有三个新的子组件。

  • TabStrip - 表示整个选项卡集。可以包含TabStripItems
  • TabStripItem - 表示单个选项卡。可以包含两个子组件 - ImageLabel - 分别表示选项卡的标题和图标。
  • TabContentItem - 表示每个选项卡的内容部分,当选择相应的选项卡时会导航到该部分。可以包含任何布局组件或新的选项卡组件。

以下是用BottomNavigation组件的新标记示例。它与Tabs组件相同。

<BottomNavigation>
    <TabStrip>
        <TabStripItem>
            <Label text="Title"></Label>
            <Image src="~/icon.png"></Image>
        </TabStripItem>
        <TabStripItem>
            <Label text="Title"></Label>
            <Image src="~/icon.png"></Image>
        </TabStripItem>
    </TabStrip>

    <TabContentItem>
        <GridLayout>
            <Label text="Content"></Label>
        </GridLayout>
    </TabContentItem>

    <TabContentItem>
        <GridLayout>
            <Label text="Content"></Label>
        </GridLayout>
    </TabContentItem>
</BottomNavigation>

这种标记声明的额外好处是它现在在所有框架中都相同。不需要指令之类的东西。当然,绑定会根据框架而有所不同。

新的样式方法

这种新的标记非常适合使用 CSS 设置样式,我们现在可以忘记像selected-tab-text-color这样的奇怪属性,并使用常规的 CSS 选择器和伪选择器。你现在可以单独设置每个选项卡的样式。

Tabs Styling

查看带有选项卡样式的 Playground 示例

诚然,让选项卡具有不同的对比色不是最佳的设计决策,但我将设计留给你。重要的是,现在可以实现更多功能。

如你所见,TabStripItem组件还支持:active伪选择器,允许你以其选中状态设置其样式。

目前,只有四个受支持的 CSS 属性可以与TabView组件实现功能奇偶性。

  • 颜色
  • 背景颜色
  • 字体(以及各个属性)
  • 文本转换

!!iOS 限制!! 你无法在 iOS Tabs组件上设置单个TabStripItem组件的样式。你可以一起在TabStrip组件上设置它们的样式。

字体图标

生成图标资源从来都不是应用程序开发中最有趣的部分。事实上,TabStripItem现在在标记中将其标题和图标分别作为ImageLabel组件,这意味着我们现在可以启用字体图标支持。你甚至可以设置其颜色,这意味着也可以设置活动状态。有人可能会说,这个功能恰逢其时,因为随着黑暗模式即将到来,你必须生成更多的图标资源。以下是一个快速示例

Tabs Font Icons

查看带有选项卡字体图标的 Playground 示例

也有新的事件

TabView的一个不幸的缺点是,你无法轻松实现选项卡重新选择模式。也就是说,如果你在某个选项卡内容中执行某些操作,然后再次选择该选项卡,则你可能希望刷新选项卡内容。我们也考虑到了这一点,为了让你处理此类场景,我们公开了新的单个事件。

  • TabStrip公开了itemTap事件,当点击任何选项卡时触发该事件。
  • TabStripItem公开了tap事件,当仅点击该特定选项卡时触发该事件。

这意味着我们现在可以轻松地执行该模式。

Tab Reselect Refresh

查看带有选项卡重新选择刷新的 Playground 示例

自定义选项卡栏

以上内容都很好,并且是对TabView组件的巨大改进,但我们希望让你拥有自由去做任何事情。NativeScript 的布局系统以及 CSS 和动画让你可以创建任何你想要的选项卡栏。如果你可以创建它,那么我们没有理由不让你在这些选项卡导航组件中使用它。

要使用自定义选项卡栏,只需从选项卡导航组件中省略TabStrip组件即可。现在的行为相同,但没有选项卡栏,你可以使用常规的 NativeScript 组件来添加你自己的选项卡栏。你可以使用选项卡导航组件的selectedIndex API 来使用你的自定义选项卡栏控制它们。

有一个非常酷的摇篮选项卡栏实现,感谢@Williamjuan27,我一直想用新组件试用一下。所以就这样做了。

Custom Cradle Tab Bar

查看自定义摇篮选项卡栏的 Playground 示例

还值得一提的是,已经有一些选项卡栏实现作为插件提供。你可以在NativeScript 市场中找到它们!

下一步

我们想做一些事情,但最终在这个版本中没有时间和资源。

  • 绑定 - TabView组件和新的BottomNavigationTabs组件实际上都不支持绑定。动态设置选项卡和内容必须通过重新创建组件来完成,这不会提供良好的用户体验。
  • 公开BottomNavigationBarTabsBar - 我们希望为你提供原生选项卡栏实现,以便你可以实现你自己的自定义选项卡导航,并仍然使用选项卡栏。

我们希望能够在将来的版本中添加这些功能。

结论

BottomNavigationTabs组件在各个方面都是TabView组件的改进版本。如果你的应用程序中使用了旧组件,请毫不犹豫地将其替换为合适的新替代方案。更好的是,创建你自己的自定义选项卡栏,并将你的应用程序提升到一个新的水平。

最终,玩得开心,别忘了分享你创建的精彩应用程序!