部分應(yīng)用在使用過(guò)程中需要自定義添加或刪除標(biāo)簽的場(chǎng)景,比如在瀏覽器中的頂部標(biāo)簽欄中需要新打開或關(guān)閉網(wǎng)頁(yè)頁(yè)簽,而這種場(chǎng)景與Tabs組件效果類似,但Tabs組件不提供增加或刪除頁(yè)簽的功能,不能自由的增加刪除頁(yè)簽,需要開發(fā)者自己實(shí)現(xiàn)Tabs中增刪頁(yè)簽功能。本文以瀏覽器中增加或刪除頁(yè)簽為例,實(shí)現(xiàn)Tabs中頁(yè)簽的增刪功能。
如下動(dòng)圖所示:
本例基于以下環(huán)境開發(fā),開發(fā)者也可以基于其他適配的版本進(jìn)行開發(fā):
本例涉及的關(guān)鍵特性以及實(shí)現(xiàn)方案如下:
整體布局分為兩部分:頁(yè)面內(nèi)容和頁(yè)簽部分。頁(yè)面視圖部分使用Tabs,其中頁(yè)簽對(duì)應(yīng)顯示的內(nèi)容需要放入TabContent組件中。頁(yè)簽部分通過(guò)@Builder自定義封裝一個(gè)tabBar組件,放入Tabs中的tabBar屬性中。
頁(yè)面視圖代碼塊:
Tabs({ barPosition: BarPosition.Start, controller: this.controller }) { ForEach(this.tabArray, (item: number) => { TabContent() { Text('我是頁(yè)面 ' + item + " 的內(nèi)容") .height('100%') .width('100%') .fontSize(30) .backgroundColor("#ffffffff") }.tabBar(this.Tab(item)) }, (item: number) => item.toString() + util.generateRandomUUID())}.barMode(BarMode.Scrollable, { margin: 30 }).onChange((index) => { this.focusIndex = index}).barHeight(30)
自定義tabBar代碼塊:
//控制頁(yè)簽渲染的數(shù)組@State tabArray: Array<number> = [0]//Tabs組件當(dāng)前顯示的頁(yè)簽@State focusIndex: number = 0//創(chuàng)建頁(yè)簽時(shí)的頁(yè)簽index@State pre: number = -1//Tabs組件控制器,根據(jù)組件下標(biāo)控制tab跳轉(zhuǎn)private controller: TabsController = new TabsController()//自定義導(dǎo)航頁(yè)簽欄@BuilderTab(tabNumber: number) { Row({ space: 20 }) { Text("頁(yè)簽 " + tabNumber).fontSize(18) Image($r('app.media.ic_public_cancel_filled')).width(20).height(20) } .justifyContent(FlexAlign.Center) .constraintSize({ minWidth: 35 }) .width(120) .height(30) .borderRadius({ topLeft: 10, topRight: 10 }) .backgroundColor(this.tabArray.indexOf(tabNumber) === this.focusIndex ? "#ffffffff" : "#ffb7b7b7")}
實(shí)現(xiàn)頁(yè)簽和頁(yè)面視圖的聯(lián)動(dòng):這里主要通過(guò)TabsController的changeIndex來(lái)實(shí)現(xiàn)對(duì)應(yīng)的試圖跳轉(zhuǎn),但需要注意由于之后會(huì)增刪數(shù)組元素的操作,所以此處傳入的index值是選擇頁(yè)面的tabNumber在數(shù)組中的索引值。
this.focusIndex = this.tabArray.indexOf(tabNumber)
增添數(shù)組元素實(shí)現(xiàn)增加頁(yè)簽的效果:增添數(shù)組元素使用數(shù)組的push方法在tabArray添加數(shù)據(jù)即可,但由于此demo原始定義的數(shù)組是連續(xù)的自然數(shù),后續(xù)增刪數(shù)組會(huì)打亂原有順序,所以此處處理為先判斷最后一個(gè)元素的值再加1,由于TabBar的渲染是通過(guò)ForEach被@State修飾的數(shù)組,因此當(dāng)tabArray中添加數(shù)據(jù)后系統(tǒng)會(huì)通知ForEach便利數(shù)組重新渲染頁(yè)面。
this.tabArray.push(this.tabArray[this.tabArray.length - 1] + 1)
通常在添加新頁(yè)面后,瀏覽器會(huì)將頁(yè)面跳轉(zhuǎn)到新添加的頁(yè)面,因此在向tabArray中完成數(shù)據(jù)推送后,需要將頁(yè)簽通過(guò)TabsController中的changeIndex方法跳轉(zhuǎn)到最后一個(gè)。
this.focusIndex = this.tabArray.length - 1this.controller.changeIndex(this.focusIndex)
當(dāng)用戶選擇另一個(gè)頁(yè)簽時(shí),可通過(guò)自定義頁(yè)簽中通用事件onClick進(jìn)行控制,當(dāng)用戶點(diǎn)擊待選擇的頁(yè)簽后,獲取當(dāng)前頁(yè)簽對(duì)應(yīng)的下標(biāo),然后通過(guò)TabsController中的changeIndex方法進(jìn)行跳轉(zhuǎn),此外可以通過(guò)更改頁(yè)簽背景顏色標(biāo)識(shí)被選中頁(yè)簽的。
.backgroundColor(this.tabArray.indexOf(tabNumber) === this.focusIndex ? "#ffffffff" : "#ffb7b7b7").onClick(() => { this.focusIndex = this.tabArray.indexOf(tabNumber) this.controller.changeIndex(this.focusIndex)})
刪除頁(yè)面有三種情況(刪除不同位置的頁(yè)面)。
if (this.pre >= 0) { this.focusIndex = this.pre} this.tabArray.splice(this.tabArray.indexOf(tabNumber), 1)
如果不是的話直接將當(dāng)前顯示頁(yè)簽下下標(biāo)設(shè)置為前一個(gè)頁(yè)簽下標(biāo),tabArray數(shù)組通過(guò)splice方法刪除頁(yè)簽,并通過(guò)TabsController完成跳轉(zhuǎn),此外頁(yè)面只要有關(guān)閉操作,頁(yè)面就不可以跳回打開該頁(yè)面的頁(yè)面,即將 pre設(shè)置為-1。
this.focusIndex = this.focusIndex - 1this.tabArray.splice(this.tabArray.indexOf(tabNumber), 1)this.pre = -1this.controller.changeIndex(this.focusIndex)
//當(dāng)前選擇頁(yè)面的對(duì)應(yīng)數(shù)組中的數(shù)據(jù)值let focusNumber = this.tabArray[this.focusIndex]//用于判斷是否是用戶在最后一個(gè)頁(yè)簽刪除當(dāng)前頁(yè)簽的情況if (this.tabArray.indexOf(focusNumber) >= 0) { this.focusIndex = this.tabArray.indexOf(focusNumber)}this.controller.changeIndex(this.focusIndex)
setTimeout(() => { this.controller.changeIndex(this.focusIndex)}, 50)
import util from '@ohos.util'@Entry@Componentstruct Drag { //控制頁(yè)簽渲染的數(shù)組 @State tabArray: Array<number> = [0] //Tabs組件當(dāng)前顯示的頁(yè)簽下標(biāo) @State focusIndex: number = 0 //創(chuàng)建頁(yè)簽時(shí)的頁(yè)簽index @State pre: number = -1 //Tabs組件控制器,根據(jù)組件下標(biāo)控制tab跳轉(zhuǎn) private controller: TabsController = new TabsController() // 單獨(dú)的頁(yè)簽 @Builder Tab(tabNumber: number) { Row({ space: 20 }) { Text("頁(yè)簽 " + tabNumber).fontSize(18) Image($r('app.media.ic_public_cancel_filled')).width(20).height(20).onClick(() => { //獲取Tabs組件當(dāng)前顯示的頁(yè)簽中顯示的數(shù)字 let focusNumber = this.tabArray[this.focusIndex] //被刪除的頁(yè)簽是否是當(dāng)前選中的頁(yè)簽,且是最后一個(gè)頁(yè)簽 if (this.focusIndex === this.tabArray.indexOf(tabNumber) && this.focusIndex == this.tabArray.length - 1) { //判斷是否需要跳回到創(chuàng)建該頁(yè)簽時(shí)的頁(yè)簽,如果不需要直接跳轉(zhuǎn)到前一個(gè)頁(yè)簽 if (this.pre >= 0) { this.focusIndex = this.pre } else { this.focusIndex = this.focusIndex - 1 } } this.tabArray.splice(this.tabArray.indexOf(tabNumber), 1) this.pre = -1 //對(duì)應(yīng)刪除頁(yè)面中的第二種情況 if (this.tabArray.indexOf(focusNumber) >= 0) { this.focusIndex = this.tabArray.indexOf(focusNumber) } //設(shè)置50ms 延遲跳轉(zhuǎn) setTimeout(() => { this.controller.changeIndex(this.focusIndex) }, 50) }) } .justifyContent(FlexAlign.Center) .constraintSize({ minWidth: 35 }) .width(120) .height(30) .borderRadius({ topLeft: 10, topRight: 10 }) .backgroundColor(this.tabArray.indexOf(tabNumber) === this.focusIndex ? "#ffffffff" : "#ffb7b7b7") .onClick(() => { this.focusIndex = this.tabArray.indexOf(tabNumber) setTimeout(() => { this.controller.changeIndex(this.focusIndex) }, 50) }) } build() { Column() { Column() { // 頁(yè)簽 // Row() { Stack() { Row({ space: 7 }) { //tabs Tabs({ barPosition: BarPosition.Start, controller: this.controller }) { ForEach(this.tabArray, (item: number) => { TabContent() { Text('我是頁(yè)面 ' + item + " 的內(nèi)容") .height('100%') .width('100%') .fontSize(30) .backgroundColor("#ffffffff") }.tabBar(this.Tab(item)) }, (item: number) => item.toString() + util.generateRandomUUID()) } .barMode(BarMode.Scrollable, { margin: 30 }) .onChange((index) => { this.focusIndex = index }) .barHeight(30) }.width("100%") Row() { Image($r('app.media.ic_public_add_filled')).onClick(() => { if (this.tabArray.length === 0) { this.tabArray.push(0) this.focusIndex = this.tabArray.length - 1 } else { this.pre = this.focusIndex this.tabArray.push(this.tabArray[this.tabArray.length - 1] + 1) this.focusIndex = this.tabArray.length - 1 } setTimeout(() => { this.controller.changeIndex(this.focusIndex) }, 50) }).width(20).height(20) }.height(30).width(30).backgroundColor("#ffb7b7b7") .justifyContent(FlexAlign.Center) } .alignContent(Alignment.TopEnd) .width('100%') .backgroundColor("#ffb7b7b7") } .alignItems(HorizontalAlign.Start) .width('100%') } .height('100%') }}
本文鏈接:http://www.www897cc.com/showinfo-26-88313-0.htmlArkUI如何實(shí)現(xiàn)增刪Tab頁(yè)簽
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com