鴻蒙應(yīng)用開發(fā)從入門到入行
第八天 - Tabs選項(xiàng)卡
導(dǎo)讀:在本篇文章里,您將掌握使用Tabs選項(xiàng)卡做欄目分類唤殴,這是未來應(yīng)用開發(fā)中極為常用的組件
首先說一聲抱歉,比較忙很久沒更新了橄维。但放心吧枣接,目前該忙的事已經(jīng)忙完,后面會恢復(fù)更新頻率硕旗。以及后續(xù)有計(jì)劃出一套免費(fèi)視頻教程窗骑,敬請期待!
本篇文章所用素材下載: media.zip
Tabs介紹
- 你是否經(jīng)常在移動端應(yīng)用里見到如下菜單分類漆枚,例如下面兩圖
像這樣的不管是在上创译,還是在下的菜單分欄功能,在HarmonyOS應(yīng)用開發(fā)中都是可以使用Tabs組件實(shí)現(xiàn)
-
每當(dāng)某個Tabs里的菜單切換后墙基,頁面內(nèi)容也會跟著改變软族,如下圖
也即:Tabs組件可以在一個頁面內(nèi)快速實(shí)現(xiàn)視圖內(nèi)容的切換
具體怎樣使用呢?我們接著往下看
Tabs - 組件基本使用
- 首先残制,Tabs里面只能放
TabContent
子組件(放其他組件會報(bào)錯)立砸,有多少個TabContent,就意味著有多少個切換視圖初茶。
如上圖所示颗祝,這段代碼里
Tabs
放了三個TabContent
,因此有三個視圖進(jìn)行切換恼布。但此時僅能實(shí)現(xiàn)左滑才能切換吐葵,根本沒有顯示出“導(dǎo)航欄”,所以一般情況下還會給TabContent
設(shè)置tabBar
屬性桥氏,用來設(shè)置對應(yīng)的導(dǎo)航欄-
如下代碼温峭,給每個TabContent都設(shè)置了tabBar屬性
@Entry @Component struct Index { build() { Tabs() { TabContent() { Text('1') }.tabBar('首頁') TabContent() { Text('2') }.tabBar('聯(lián)系人') TabContent() { Text('3') }.tabBar('我的') } } }
-
此時效果如下
-
小結(jié):
- Tabs里只能放TabContent
- TabContent有多少個就意味著有多少個視圖切換
- TabContent配合tabBar屬性,即可設(shè)置導(dǎo)航欄標(biāo)題字支,tabBar傳入字符串凤藏,字符串是什么奸忽,標(biāo)題即為什么
修改導(dǎo)航欄位置到底部
默認(rèn)情況下,導(dǎo)航欄在頁面上方揖庄,如果想把導(dǎo)航欄設(shè)置到頁面底部顯示栗菜,可以通過給
Tabs
傳入?yún)?shù)barPosition
來實(shí)現(xiàn)-
代碼如下:
Tabs({ barPosition: BarPosition.End }) { // .... 省略里面的TabContent代碼 }
此時界面效果如下圖
- 如上代碼所示:barPosition參數(shù),需要傳入BarPosition的枚舉蹄梢,這個枚舉僅有兩個值:Start與End疙筹,默認(rèn)即為Start,代表在頂部禁炒,設(shè)置為End即為底部
修改導(dǎo)航欄位置到側(cè)邊
那么是不是只有頂部而咆、底部兩種位置呢?其實(shí)不然幕袱,還可以設(shè)置左側(cè)或右側(cè)暴备,這里需要用到Tabs的一個屬性,即為:
vertical
這個屬性代表:是否垂直擺放導(dǎo)航欄们豌,那換句話說即為是否豎著放(也即側(cè)邊放)涯捻,默認(rèn)為false即水平擺放。
-
我們試著把這個屬性改為true望迎,如下代碼
Tabs({ barPosition: BarPosition.Start }) { // 省略里面的TabContent代碼 } .vertical(true) .barWidth(80) .barBackgroundColor('#f00')
-
效果如下圖
-
代碼解釋:
- 因?yàn)関ertical屬性設(shè)置為true障癌,必然是在側(cè)邊擺放導(dǎo)航欄,但為什么是左邊呢辩尊?因?yàn)門abs的
barPosition
參數(shù)設(shè)置為Start(默認(rèn)值)混弥,即為在左側(cè),所以如果barPosition
設(shè)置為BarPosition.End
对省,即為在右側(cè)。 - barWidth是設(shè)置導(dǎo)航條的寬度(側(cè)邊方向是設(shè)置寬度)或高度(上下方向是設(shè)置高度)
- barBackgroundColor是設(shè)置導(dǎo)航條背景顏色晾捏,這里加背景色主要是為了讓大家能看到我們設(shè)置的寬度生效了
- 因?yàn)関ertical屬性設(shè)置為true障癌,必然是在側(cè)邊擺放導(dǎo)航欄,但為什么是左邊呢辩尊?因?yàn)門abs的
- 小結(jié):
- 如果Tabs不設(shè)置vertical或者vertical設(shè)置為false蒿涎,導(dǎo)航欄方向都是上下擺放,至于是上還是下跟barPosition有關(guān)惦辛,Start為上劳秋,End為下
- 如果Tabs設(shè)置了vertical為true,導(dǎo)航欄方向都是側(cè)邊擺放胖齐,至于是左還是右跟barPosition有關(guān)玻淑,Start為左,End為右
Tabs嵌套使用
-
很多時候我們的App應(yīng)用場景其實(shí)需要頂部呀伙、底部都有導(dǎo)航欄补履,即整個App分為“首頁”、“發(fā)現(xiàn)”剿另、“推薦”
箫锤、“我的”四個部分贬蛙,但是在“首頁”里,又分為:關(guān)注谚攒、視頻阳准、游戲、數(shù)碼馏臭、科技四個板塊野蝇,如下圖所示
-
這時候就需要嵌套導(dǎo)航欄(在首頁這個視圖里再套一個Tabs),代碼如下
Tabs({ barPosition: BarPosition.End }) { TabContent() { // 在首頁這個視圖里括儒,又分為關(guān)注绕沈、視頻、游戲塑崖、數(shù)碼七冲、科技四個切換分類 Tabs() { TabContent() { Text('關(guān)注的內(nèi)容') }.tabBar('關(guān)注') TabContent() { Text('視頻的內(nèi)容') }.tabBar('視頻') TabContent() { Text('游戲的內(nèi)容') }.tabBar('游戲') TabContent() { Text('數(shù)碼的內(nèi)容') }.tabBar('數(shù)碼') TabContent() { Text('科技的內(nèi)容') }.tabBar('科技') } }.tabBar('首頁') TabContent() { Text('發(fā)現(xiàn)的內(nèi)容') }.tabBar('發(fā)現(xiàn)') TabContent() { Text('推薦的內(nèi)容') }.tabBar('推薦') TabContent() { Text('我的內(nèi)容') }.tabBar('我的') }
限制導(dǎo)航欄滾動
默認(rèn)情況下所有的
Tabs
的導(dǎo)航都具備滾動的功能,但是當(dāng)我們使用Tabs嵌套時规婆,如上面的場景澜躺,會發(fā)現(xiàn)底部的導(dǎo)航欄有滾動,首頁里嵌套的導(dǎo)航欄也有滾動抒蚜。為了避免他們沖突掘鄙,一般我們會讓底部的大導(dǎo)航欄禁止?jié)L動。-
如何禁止?jié)L動呢嗡髓?
- 使用
scrollable
屬性操漠,設(shè)置為false即可
- 使用
-
例
Tabs({ barPosition: BarPosition.End }) { TabContent() { // 在首頁這個視圖里,又分為關(guān)注饿这、視頻浊伙、游戲、數(shù)碼长捧、科技四個切換分類 Tabs() { // 省略這個嵌套的代碼 } }.tabBar('首頁') TabContent() { Text('發(fā)現(xiàn)的內(nèi)容') }.tabBar('發(fā)現(xiàn)') TabContent() { Text('推薦的內(nèi)容') }.tabBar('推薦') TabContent() { Text('我的內(nèi)容') }.tabBar('我的') } .scrollable(false)
自定義導(dǎo)航欄
- 我們很多應(yīng)用的底部導(dǎo)航欄嚣鄙,其實(shí)一般除了標(biāo)題文字外,還會附帶圖標(biāo)串结,例如下圖
這時候需要我們使用
@Builder
裝飾器自定義導(dǎo)航欄的布局后哑子,再傳遞給tabBar-
如下代碼
tabBuilder(title: string, icon: ResourceStr) { Column({ space: 2 }) { Image(icon) .width(30) Text(title) } .width('100%') .height(50) .justifyContent(FlexAlign.Center) }
- 這個Builder聲明一個垂直布局的UI,上為圖標(biāo)肌割,下為文字(標(biāo)題)卧蜓,但此時這個Builder跟每個tabBar還沒有任何關(guān)聯(lián),因此需要做調(diào)用綁定
-
代碼如下
Tabs({ barPosition: BarPosition.End }) { TabContent() { // ... }.tabBar(this.tabBuilder('首頁', $r('app.media.ic_public_home'))) TabContent() { // ... }.tabBar(this.tabBuilder('信息', $r('app.media.ic_public_comments'))) TabContent() { // ... }.tabBar(this.tabBuilder('相冊', $r('app.media.ic_public_albums'))) TabContent() { // ... }.tabBar(this.tabBuilder('我的', $r('app.media.ic_public_contacts'))) }
-
此時得到效果如下圖
我們會發(fā)現(xiàn)把敞,不管點(diǎn)擊哪一個弥奸,都不會有高亮效果。這是因?yàn)槭褂米远x導(dǎo)航欄后奋早,需要自行在Builder里根據(jù)當(dāng)前選中下標(biāo)來判斷顯示不同的圖標(biāo)和顏色
-
綜上所述其爵,我們應(yīng)該先聲明一個狀態(tài)變量冒冬,記錄當(dāng)前選中的索引
@State currentIndex: number = 0 // 默認(rèn)為0,代表默認(rèn)讓第一個導(dǎo)航高亮
-
修改Builder摩渺,代碼如下
@Builder tabBuilder(title: string, icon: ResourceStr, selectIcon: ResourceStr, index: number) { Column({ space: 2 }) { Image(this.currentIndex === index ? selectIcon : icon) .width(30) .fillColor(this.currentIndex === index ? '#0094ff' : '#000') Text(title) .fontColor(this.currentIndex === index ? '#0094ff' : '#000') } .width('100%') .height(50) .justifyContent(FlexAlign.Center) }
-
代碼解釋:
- 首先參數(shù)上新增了selectIcon與index简烤,分別代表選中時要顯示的圖片,以及當(dāng)前的tabBar自身索引
- 代碼內(nèi)根據(jù)我們記錄的導(dǎo)航索引摇幻,與傳入的當(dāng)前tabBar自身索引做比較横侦。相等就意味著當(dāng)前tabBar被選中,所以讓其使用選中的圖片绰姻,以及設(shè)置選中的顏色枉侧。否則用默認(rèn)的圖片與顏色
效果如下
切換指定頁簽
此時我們發(fā)現(xiàn),之前在不使用自定義導(dǎo)航欄時狂芋,默認(rèn)的Tabs會實(shí)現(xiàn)切換邏輯榨馁,也即點(diǎn)誰誰高亮。但使用自定義導(dǎo)航欄后帜矾,發(fā)現(xiàn)點(diǎn)擊導(dǎo)航欄沒有切換高亮效果翼虫。
原因:自定義導(dǎo)航欄是根據(jù)我們的自定義Builder來決定顯示狀態(tài)的,如果需要高亮隨之改變屡萤,就需要把我們聲明的記錄索引的狀態(tài)變量進(jìn)行修改珍剑,也即上面聲明的
currentIndex
。此時因?yàn)?code>currentIndex一直是0死陆,所以一直是第一個首頁高亮招拙。因此,我們需要頁簽改變時讓currentIndex的值也跟著改變-
這是需要用到
Tabs
提供的onChange
事件措译,監(jiān)聽索引變化别凤,并將當(dāng)前切換后的索引值賦值給currentIndex,代碼如下Tabs({ barPosition: BarPosition.End }) { // 省略中間代碼 } .onChange(index => { this.currentIndex = index })
-
以上利用
onChange
可以實(shí)現(xiàn)以外领虹,其實(shí)在Next加入$$雙向綁定后也能實(shí)現(xiàn)规哪,做法是,只要將currentIndex與Tabs的index參數(shù)做雙向綁定即可實(shí)現(xiàn)掠械,代碼如下Tabs({ barPosition: BarPosition.End, index: $$this.currentIndex }) { // 省略里面內(nèi)容 }
使用雙向綁定還有個好處是:如果將來需要用代碼改變頁簽,只需要改
currentIndex
的值即可注祖,例如:this.currentIndex = 2
即會切換到頁簽索引為2的導(dǎo)航
總結(jié)
今日主要講解了Tabs的使用猾蒂,Tabs是一種視圖切換的組件。
默認(rèn)情況下是晨,Tabs是在頂部顯示肚菠,如果要改位置可以通過barPosition參數(shù)來修改
如果需要展示在側(cè)邊,可以通過 vertical 屬性設(shè)置為true來實(shí)現(xiàn)
如果需要帶圖帶標(biāo)題的自定義導(dǎo)航欄罩缴,可以用@Builder進(jìn)行封裝并傳入tabBar
課后練習(xí)
- 判斷題
- 當(dāng)設(shè)置vertical為true時蚊逢,導(dǎo)航欄在右側(cè)顯示
- 當(dāng)Tabs的barPosition為End层扶,vertical為false時秩铆,導(dǎo)航欄在右側(cè)顯示
- 簡單題
- 請回答园爷,直接設(shè)置Tabs的vertical為true,導(dǎo)航欄在哪顯示琳钉?
預(yù)告:下一篇內(nèi)容
-
下一篇將做個鴻蒙官網(wǎng)的經(jīng)典案例:新聞數(shù)據(jù)终抽,即本頁一開始的圖如下戳表,敬請期待