鴻蒙應(yīng)用開發(fā)從入門到入行 - 篇8:Tabs選項(xiàng)卡頁簽視圖切換

鴻蒙應(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)用里見到如下菜單分類漆枚,例如下面兩圖
image.png
image.png
  • 像這樣的不管是在上创译,還是在下的菜單分欄功能,在HarmonyOS應(yīng)用開發(fā)中都是可以使用Tabs組件實(shí)現(xiàn)

  • 每當(dāng)某個Tabs里的菜單切換后墙基,頁面內(nèi)容也會跟著改變软族,如下圖


    gif.gif
  • 也即:Tabs組件可以在一個頁面內(nèi)快速實(shí)現(xiàn)視圖內(nèi)容的切換

  • 具體怎樣使用呢?我們接著往下看

Tabs - 組件基本使用

  • 首先残制,Tabs里面只能放 TabContent子組件(放其他組件會報(bào)錯)立砸,有多少個TabContent,就意味著有多少個切換視圖初茶。
gif-3447925.gif
  • 如上圖所示颗祝,這段代碼里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('我的')
        }
      }
    }
    
  • 此時效果如下


    image.png
  • 小結(jié):

    1. Tabs里只能放TabContent
    2. TabContent有多少個就意味著有多少個視圖切換
    3. 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代碼
    }
    
  • 此時界面效果如下圖

image.png
  • 如上代碼所示: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')
    
  • 效果如下圖


    image.png
  • 代碼解釋:

    • 因?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è)置的寬度生效了
  • 小結(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ù)碼馏臭、科技四個板塊野蝇,如下圖所示


    image.png
  • 這時候就需要嵌套導(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)串结,例如下圖
image.png
  • 這時候需要我們使用@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')))
    }
    
  • 此時得到效果如下圖


    image.png
  • 我們會發(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)的圖片與顏色
  • 效果如下

image.png

切換指定頁簽

  • 此時我們發(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ù)终抽,即本頁一開始的圖如下戳表,敬請期待


    image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市昼伴,隨后出現(xiàn)的幾起案子匾旭,更是在濱河造成了極大的恐慌,老刑警劉巖圃郊,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件价涝,死亡現(xiàn)場離奇詭異,居然都是意外死亡持舆,警方通過查閱死者的電腦和手機(jī)色瘩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吏廉,“玉大人泞遗,你說我怎么就攤上這事∠玻” “怎么了史辙?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長佩伤。 經(jīng)常有香客問我聊倔,道長,這世上最難降的妖魔是什么生巡? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任耙蔑,我火速辦了婚禮,結(jié)果婚禮上孤荣,老公的妹妹穿的比我還像新娘甸陌。我一直安慰自己,他們只是感情好盐股,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布钱豁。 她就那樣靜靜地躺著,像睡著了一般疯汁。 火紅的嫁衣襯著肌膚如雪牲尺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天,我揣著相機(jī)與錄音谤碳,去河邊找鬼溃卡。 笑死,一個胖子當(dāng)著我的面吹牛蜒简,可吹牛的內(nèi)容都是我干的瘸羡。 我是一名探鬼主播,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼臭蚁,長吁一口氣:“原來是場噩夢啊……” “哼最铁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起垮兑,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤冷尉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后系枪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雀哨,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年私爷,在試婚紗的時候發(fā)現(xiàn)自己被綠了雾棺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡衬浑,死狀恐怖捌浩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情工秩,我是刑警寧澤尸饺,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站助币,受9級特大地震影響浪听,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜眉菱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一迹栓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧俭缓,春花似錦克伊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至季春,卻和暖如春洗搂,著一層夾襖步出監(jiān)牢的瞬間消返,已是汗流浹背载弄。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工耘拇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人宇攻。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓惫叛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親逞刷。 傳聞我的和親對象是個殘疾皇子嘉涌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內(nèi)容