当前位置:   article > 正文

HarmonyOs开发:导航tabs组件封装与使用_harmonyos tabs封装

harmonyos tabs封装

前言

主页的底部导航以及页面顶部的切换导航,无论哪个系统,哪个App,都是最常见的功能之一,虽然说在鸿蒙中有现成的组件tabs可以很快速的实现,但是在使用的时候,依然有几个潜在的问题存在,第一,当导航较少时,tabs是默认居中模式,目前无法进行居左,在有这样功能的时候,难以满足需求;第二,导航右侧需要展示按钮的时候,tabs也是无法满足的;除此之外,还有很多人都非常关心的问题,底部的指示器可以跟随页面的滑动而滑动;面对着种种问题的存在,系统的tabs改进之路仍然很艰巨。

本篇的文章内容如下:

1、封装tabs效果及基本使用

2、主要的封装实现分析

3、开源地址

4、相关总结

一、封装tabs效果及基本使用

所有的效果都是基于tabs组件进行拓展的。

(功能项)

(底部Tab)

(普通导航)

(居左导航)

(右边按钮)

以上就是封装后的部分效果,目前已经上传到了远程仓库,大家可以按照以下的方式进行使用。

方式一:在Terminal窗口中,执行如下命令安装三方包,DevEco Studio会自动在工程的oh-package.json5中自动添加三方包依赖。

ohpm install @abner/tab

方式二:在工程的oh-package.json5中设置三方包依赖,配置示例如下:

"dependencies": { "@abner/tab": "^1.0.0"}

1、底部导航案例

相关效果:

代码实现:

  1. @Entry
  2. @Component
  3. struct BottomTabPage1 {
  4. /**
  5. * AUTHOR:AbnerMing
  6. * INTRODUCE:tab对应的页面
  7. * @param index 索引
  8. * @param item TabBar对象,非必须
  9. * */
  10. @Builder
  11. itemPage(index: number, item: TabBar) {
  12. Text(item.title)
  13. }
  14. build() {
  15. Column() {
  16. ActionBar({ title: "底部导航案例一" })
  17. BottomTabLayout({
  18. itemPage: this.itemPage,//tab对应的页面
  19. tabSelectedColor: "#D81E06",//文字未选择颜色
  20. tabNormalColor: Color.Black,//文字未选择颜色
  21. tabLabelMarginTop: 10,//文字距离图片的高度
  22. tabScrollable: true,//是否可以滑动
  23. tabMarginBottom: 30, //距离底部的距离,一般可以获取底部导航栏的高度,然后进行设置
  24. onChangePage: (position) => {
  25. //页面切换
  26. },
  27. onTabBarClick: (position) => {
  28. //tab点击
  29. },
  30. tabBar: [
  31. new TabBar("首页", $r("app.media.ic_home_select"), $r("app.media.ic_home_unselect")),
  32. new TabBar("网络", $r("app.media.ic_net_select"), $r("app.media.ic_net_unselect")),
  33. new TabBar("列表", $r("app.media.ic_list_select"), $r("app.media.ic_list_unselect")),
  34. new TabBar("组件", $r("app.media.ic_view_select"), $r("app.media.ic_view_unselect"))
  35. ]
  36. })
  37. }.height("100%")
  38. }
  39. }

相关属性

属性

类型

概述

itemPage

BuilderParam

tab对应得页面

tabSelectedColor

ResourceColor

tab选中颜色

tabNormalColor

ResourceColor

tab未选中颜色

tabSelectedBgColor

ResourceColor

选中背景颜色

tabNormalBgColor

ResourceColor

未选中背景颜色

tabIconWidth

number

图片icon的宽度,默认20

tabIconHeight

number

图片icon的高度,默认20

tabSize

number

tab文字大小

tabWeight

number /FontWeight / string

文字权重

tabLabelMarginTop

number

标签距离图片的高度

tabBar

Array<TabBar>

tab数据源

tabWidth

Length

tab指示器的宽度

tabHeight

number

tab指示器的高度,默认56

currentIndex

number

当前索引,默认是第一个

onChangePage

回调方法

页面切换监听

onTabBarClick

tab点击回调

tab点击监听

tabScrollable

boolean

是否可滑动,默认不可以滑动

tabMarginBottom

number

tab距离底部的距离

2、底部导航案例2,自定义Tab视图

相关效果:

代码实现:

  1. @Entry
  2. @Component
  3. struct BottomTabPage2 {
  4. private currentIndex = 0 //默认是第一个
  5. /**
  6. * AUTHOR:AbnerMing
  7. * INTRODUCE:tab对应的页面
  8. * @param index 索引
  9. * @param item TabBar对象,非必须
  10. * */
  11. @Builder
  12. itemPage(index: number, item: TabBar) {
  13. Text(item.title)
  14. }
  15. /**
  16. * AUTHOR:AbnerMing
  17. * INTRODUCE:自定义Tab视图,自己绘制
  18. * @param index 索引
  19. * @param item TabBar对象,非必须
  20. * */
  21. @Builder
  22. itemTab(index: number, item: TabBar) {
  23. Column() {
  24. Image(this.currentIndex == index ? item.selectedIcon
  25. : item.normalIcon)
  26. .width(30).height(30)
  27. Text(item.title)
  28. .fontColor(this.currentIndex == index ? "#D81E06" : "#000000")
  29. .fontSize(14)
  30. .margin({ top: 5 })
  31. }.width("100%")
  32. }
  33. build() {
  34. Column() {
  35. ActionBar({ title: "底部导航案例二" })
  36. BaseBottomTabLayout({
  37. itemPage: this.itemPage,
  38. itemTab: this.itemTab,
  39. tabBar: [
  40. new TabBar("首页", $r("app.media.ic_home_select"), $r("app.media.ic_home_unselect")),
  41. new TabBar("网络", $r("app.media.ic_net_select"), $r("app.media.ic_net_unselect")),
  42. new TabBar("列表", $r("app.media.ic_list_select"), $r("app.media.ic_list_unselect")),
  43. new TabBar("组件", $r("app.media.ic_view_select"), $r("app.media.ic_view_unselect"))
  44. ],
  45. tabMarginBottom: 30, //距离底部的距离,一般可以获取底部导航栏的高度,然后进行设置
  46. onTabBarClick: (position) => {
  47. //tab点击
  48. console.log("====点击了Tab" + position)
  49. },
  50. onChangePage: (position) => {
  51. //页面切换
  52. console.log("====页面切换了" + position)
  53. }
  54. })
  55. }
  56. }
  57. }

相关属性

属性

类型

概述

itemPage

BuilderParam

tab对应得页面

tabSelectedColor

ResourceColor

tab选中颜色

tabNormalColor

ResourceColor

tab未选中颜色

tabSelectedBgColor

ResourceColor

选中背景颜色

tabNormalBgColor

ResourceColor

未选中背景颜色

tabIconWidth

number

图片icon的宽度,默认20

tabIconHeight

number

图片icon的高度,默认20

tabSize

number

tab文字大小

tabWeight

number /FontWeight / string

文字权重

tabLabelMarginTop

number

标签距离图片的高度

tabBar

Array<TabBar>

tab数据源

tabWidth

Length

tab指示器的宽度

tabHeight

number

tab指示器的高度,默认56

currentIndex

number

当前索引,默认是第一个

onChangePage

回调方法

页面切换监听

onTabBarClick

tab点击回调

tab点击监听

tabScrollable

boolean

是否可滑动,默认不可以滑动

tabMarginBottom

number

tab距离底部的距离

isMarginBottom

boolean

默认开启,tab距离底部的距离

3、普通指示器导航

相关效果:

代码实现:

  1. @Entry
  2. @Component
  3. struct TabLayoutPage1 {
  4. @Builder
  5. itemPage(index: number, item: string) {
  6. Text(item)
  7. }
  8. build() {
  9. Column() {
  10. ActionBar({ title: "封装导航【普通】" })
  11. TabLayout({
  12. tabBar: ["条目一", "条目二"],
  13. itemPage: this.itemPage,
  14. tabAttribute: (tab) => {
  15. //设置属性
  16. },
  17. onChangePage: (position) => {
  18. //页面改变
  19. console.log("页面改变:" + position)
  20. },
  21. onTabBarClick: (position) => {
  22. //点击改变
  23. console.log("点击改变:" + position)
  24. }
  25. })
  26. }
  27. }
  28. }

相关属性

属性

类型

概述

tabWidth

Length

tab指示器的宽度

tabHeight

number

tab指示器的高度

onChangePage

回调方法(position: number)

页面改变回调

currentIndex

number

当前索引,默认第0个

tabScrollable

boolean

是否可以滑动切换页面,默认可以滑动

tabBar

Array<string>

数据源

itemPage

回调方法BuilderParam (index: number, item: string)

tab对应得页面

tabAttribute

回调方法(attribute: TabModel)

设置tab相关属性

isHideDivider

boolean

是否隐藏下划线,默认展示

isTabAlignLeft

boolean

是否从最左边开始,默认不是

barMode

BarMode

是均分还是可滑动,默认滑动

onTabBarClick

回调方法(position: number)

tab点击回调

isShowTabMenu

boolean

是否展示右边的按钮选项,默认不展示

tabMenu

回调方法BuilderParam

右边展示的按钮视图

tabMenuWidth

number

tab右侧按钮的宽度

tabMenuMarginRight

number

tab按钮距离右侧的距离

4、普通指示器导航【均分】

相关效果:

代码实现:

  1. @Entry
  2. @Component
  3. struct TabLayoutPage2 {
  4. @Builder
  5. itemPage(index: number, item: string) {
  6. Text(item)
  7. }
  8. build() {
  9. Column() {
  10. ActionBar({ title: "封装导航【均分】" })
  11. TabLayout({
  12. tabBar: ["条目一", "条目二", "条目三", "条目四"],
  13. barMode: BarMode.Fixed, //均分
  14. itemPage: this.itemPage,
  15. tabAttribute: (tab) => {
  16. //设置属性
  17. },
  18. onChangePage: (position) => {
  19. //页面改变
  20. console.log("页面改变:" + position)
  21. },
  22. onTabBarClick: (position) => {
  23. //点击改变
  24. console.log("点击改变:" + position)
  25. }
  26. })
  27. }
  28. }
  29. }

相关属性

同上。

5、普通指示器导航【居左】

相关效果:

代码实现:

  1. @Entry
  2. @Component
  3. struct TabLayoutPage4 {
  4. @Builder
  5. itemPage(index: number, item: string) {
  6. Text(item)
  7. }
  8. build() {
  9. Column() {
  10. ActionBar({ title: "封装导航【居左】" })
  11. TabLayout({
  12. tabBar: ["条目一", "条目二"],
  13. isTabAlignLeft: true,
  14. itemPage: this.itemPage,
  15. tabAttribute: (tab) => {
  16. //设置属性
  17. },
  18. onChangePage: (position) => {
  19. //页面改变
  20. console.log("页面改变:" + position)
  21. }
  22. })
  23. }
  24. }
  25. }

相关属性

同上。

6、普通指示器导航【右边添加按钮】

相关效果:

代码实现:

  1. @Entry
  2. @Component
  3. struct TabLayoutPage6 {
  4. @Builder
  5. itemPage(index: number, item: string) {
  6. Text(item)
  7. }
  8. /**
  9. * AUTHOR:AbnerMing
  10. * INTRODUCE:右侧的按钮,可以是任何的视图
  11. * */
  12. @Builder
  13. itemMenu() {
  14. Text("测试")
  15. .backgroundColor(Color.Pink)
  16. .width("100%")
  17. .height("100%")
  18. .textAlign(TextAlign.Center)
  19. }
  20. build() {
  21. Column() {
  22. ActionBar({ title: "封装导航【居左滑动】" })
  23. TabLayout({
  24. tabBar: ["条目一", "条目二", "条目三", "条目四", "条目五", "条目六"],
  25. isTabAlignLeft: true,
  26. itemPage: this.itemPage,
  27. isShowTabMenu: true, //展示右侧的按钮
  28. tabMenu: this.itemMenu, //按钮
  29. tabMenuWidth: 100, //按钮宽度
  30. tabAttribute: (tab) => {
  31. //设置属性
  32. },
  33. onChangePage: (position) => {
  34. //页面改变
  35. console.log("页面改变:" + position)
  36. }
  37. })
  38. }
  39. }
  40. }

相关属性

同上。

二、主要的封装实现分析

大部分的封装都是基于系统提供的Api实现的,无非就是简化了相关代码,基本上都不难,大家可以直接查看源码即可,这里重点说下普通导航的居左效果。

在文章开头的时候已经阐述,目前的tabs是不支持居左的,如果要实现居左的效果,就要自己自定义,这里使用的是横向的List组件实现的,通过Scroller来控制滑动距离。

  1. List({ scroller: this.scroller }) {
  2. ForEach(this.tabBar, (item: string, index: number) => {
  3. ListItem() {
  4. this.tabItem(index, item)
  5. }.height(this.tabHeight)
  6. .onClick(() => {
  7. //条目点击
  8. if (this.isTabAlignLeft) {
  9. //自定义滑动
  10. if (index > this.currentIndex) {
  11. this.scroller.scrollBy(20 * (index + 1), 0)
  12. } else {
  13. this.scroller.scrollBy(-20 * (this.tabBar.length - index), 0)
  14. }
  15. }
  16. this.currentIndex = index
  17. })
  18. }, (item: string) => item)
  19. }
  20. .listDirection(Axis.Horizontal)
  21. .width(this.tabListWidth)
  22. .height(this.tabHeight)
  23. .scrollBar(BarState.Off)

需要注意的是,如果采用居左的效果,那么系统的tabBar我们就要舍弃,如下代码,如果居左,采用上述自定义tabBar,否则采用系统自定义的。

  1. //使用tabBar对象形式传递
  2. if (this.isTabAlignLeft) {
  3. ForEach(this.tabBar, (item: string, index) => {
  4. TabContent() {
  5. this.itemPage(index, item)
  6. }
  7. })
  8. } else {
  9. ForEach(this.tabBar, (item: string, index) => {
  10. TabContent() {
  11. this.itemPage(index, item)
  12. }.tabBar(this.tabItem(index, item))
  13. })
  14. }

至于右侧的按钮布局,其实和自定义tabBar一致,采用的是RelativeContainer组件,包裹住按钮组件和tabBar组件即可,当然了,更多的代码,大家还是查看源码比较好,代码里的注释写的比较详细。

三、开源地址

地址中也有详细的使用概述:

https://ohpm.openharmony.cn/#/cn/detail/@abner%2Ftab

四、相关总结

指示器随着手势滑动,系统中的Api是支持的,但是需要实现的代码量很多,而且模式只支持Fixed,那么在导航条目较多的情况下,这个模式是很不符合需求的,当然了,我也在一步一步优化中,也希望在较短的时间内可以实现,大家可以持续关注。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/644092
推荐阅读
相关标签
  

闽ICP备14008679号