精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

鴻蒙ArkUI開發-實現增刪Tab頁簽

jf_46214456 ? 2024-01-29 18:43 ? 次閱讀

場景介紹

部分應用在使用過程中需要自定義添加或刪除標簽的場景,比如在瀏覽器中的頂部標簽欄中需要新打開或關閉網頁頁簽,而這種場景與Tabs組件效果類似,但Tabs組件不提供增加或刪除頁簽的功能,不能自由的增加刪除頁簽,需要開發者自己實現Tabs中增刪頁簽功能。本文以瀏覽器中增加或刪除頁簽為例,實現Tabs中頁簽的增刪功能。

效果呈現

如下動圖所示:

環境要求

本例基于以下環境開發,開發者也可以基于其他適配的版本進行開發:

  • IDE: DevEco Studio 4.0 Release
  • SDK: Ohos_sdk_public 4.0.10.13 (API Version 10 Release)

實現原理

本例涉及的關鍵特性以及實現方案如下:

  • 通過@Builder自定義封裝一個導航頁簽欄,并通過ForEach完成對Tabs組件的內容頁和導航頁簽欄的動態渲染。
  • 通過TabsController的changeIndex可實現頁面的跳轉,傳入的index是數組中對應的索引值。
  • 頁簽的增加通過數組的push方法,增加數組元素。
  • 刪除頁簽通過通過刪除頁面對應數組的索引值處的數據完成,刪除后頁面跳轉位置根據業務邏輯要求確定跳轉頁面對應的索引值。

開發步驟

  1. 整體布局分為兩部分:頁面內容和頁簽部分。頁面視圖部分使用Tabs,其中頁簽對應顯示的內容需要放入TabContent組件中。頁簽部分通過@Builder自定義封裝一個tabBar組件,放入Tabs中的tabBar屬性中。
    頁面視圖代碼塊:

    Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
      ForEach(this.tabArray, (item: number) = > {
        TabContent() {
          Text('我是頁面 ' + item + " 的內容")
            .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代碼塊:

    //控制頁簽渲染的數組
    @State tabArray: Array< number > = [0]
    //Tabs組件當前顯示的頁簽
    @State focusIndex: number = 0
    //創建頁簽時的頁簽index
    @State pre: number = -1
    //Tabs組件控制器,根據組件下標控制tab跳轉
    private controller: TabsController = new TabsController()
    
    //自定義導航頁簽欄
    @Builder
    Tab(tabNumber: number) {
      Row({ space: 20 }) {
        Text("頁簽 " + 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")
    }
    
  2. 實現頁簽和頁面視圖的聯動:這里主要通過TabsController的changeIndex來實現對應的試圖跳轉,但需要注意由于之后會增刪數組元素的操作,所以此處傳入的index值是選擇頁面的tabNumber在數組中的索引值。

    this.focusIndex = this.tabArray.indexOf(tabNumber)
    
  3. 增添數組元素實現增加頁簽的效果:增添數組元素使用數組的push方法在tabArray添加數據即可,但由于此demo原始定義的數組是連續的自然數,后續增刪數組會打亂原有順序,所以此處處理為先判斷最后一個元素的值再加1,由于TabBar的渲染是通過ForEach被@State修飾的數組,因此當tabArray中添加數據后系統會通知ForEach便利數組重新渲染頁面。

    this.tabArray.push(this.tabArray[this.tabArray.length - 1] + 1)
    
  4. 通常在添加新頁面后,瀏覽器會將頁面跳轉到新添加的頁面,因此在向tabArray中完成數據推送后,需要將頁簽通過TabsController中的changeIndex方法跳轉到最后一個。

    this.focusIndex = this.tabArray.length - 1
    this.controller.changeIndex(this.focusIndex)
    
  5. 當用戶選擇另一個頁簽時,可通過自定義頁簽中通用事件onClick進行控制,當用戶點擊待選擇的頁簽后,獲取當前頁簽對應的下標,然后通過TabsController中的changeIndex方法進行跳轉,此外可以通過更改頁簽背景顏色標識被選中頁簽的。

    .backgroundColor(this.tabArray.indexOf(tabNumber) === this.focusIndex ? "#ffffffff" : "#ffb7b7b7")
    .onClick(() = > {
      this.focusIndex = this.tabArray.indexOf(tabNumber)
      this.controller.changeIndex(this.focusIndex)
    })
    
  6. 刪除頁面有三種情況(刪除不同位置的頁面)。

    • 第一種情況是被關閉頁面為最后一個頁面,且當前選中的頁面為最后一個頁面,如果當前被選中頁面是剛剛被其他頁面創建的情況,因此頁面需要跳回到創建被刪除頁簽的頁簽(邏輯參考chrome瀏覽器)

      if (this.pre >= 0) {
        this.focusIndex = this.pre
      } 
      this.tabArray.splice(this.tabArray.indexOf(tabNumber), 1)
      

      如果不是的話直接將當前顯示頁簽下下標設置為前一個頁簽下標,tabArray數組通過splice方法刪除頁簽,并通過TabsController完成跳轉,此外頁面只要有關閉操作,頁面就不可以跳回打開該頁面的頁面,即將 pre設置為-1。

      this.focusIndex = this.focusIndex - 1
      this.tabArray.splice(this.tabArray.indexOf(tabNumber), 1)
      this.pre = -1
      this.controller.changeIndex(this.focusIndex)
      
    • 第二種情況,當用戶當前選擇的不是最后一個標簽,然后直接刪除其他頁簽時,可以直接刪除刪除,但是需要重新計算當前選中頁簽在tabArray中的實時位置,到新注意需要排除用戶在最后一個頁簽刪除當前頁簽的情況。

      //當前選擇頁面的對應數組中的數據值
      let focusNumber = this.tabArray[this.focusIndex]
      //用于判斷是否是用戶在最后一個頁簽刪除當前頁簽的情況
      if (this.tabArray.indexOf(focusNumber) >= 0) {
        this.focusIndex = this.tabArray.indexOf(focusNumber)
      }
      this.controller.changeIndex(this.focusIndex)
      
    • 第三種情況,當用戶當前選擇的不是最后一個標簽,且刪除被選中頁面,直接刪除,然后通過TabsController完成跳轉,不需要額外操作。

    說明

    • 由于Tabs組件中的導航頁簽欄會占滿屏幕,導致添加按鈕無法直接添加到與頁簽直接平齊的位置,因此通過層疊布局(Stack)的方式,將添加頁簽按鈕覆蓋到Tabs組件上,通過Stack中的對齊方式將添加按鈕調整到合適位置。
    • 用于Tabs添加或刪除子節點時,ForEach需要重新將所有頁簽進行重新渲染,如果在添加或刪除完頁簽后直接調用TabsController中的changeIndex進行跳轉,頁面無法調到指定頁簽。這是由于ForEach還未將組件渲染完成,將子組件掛載到Tabs中,因此建議通過setTimeOut延遲一段時間再進行跳轉,經過驗證大概50ms后即可,開發者可再自行驗證。
    setTimeout(() = > {
     this.controller.changeIndex(this.focusIndex)
    }, 50)
    

完整實例

完整示例代碼如下:

import util from '@ohos.util'

@Entry
@Component
struct Drag {
  //控制頁簽渲染的數組
  @State tabArray: Array< number > = [0]
  //Tabs組件當前顯示的頁簽下標
  @State focusIndex: number = 0
  //創建頁簽時的頁簽index
  @State pre: number = -1
  //Tabs組件控制器,根據組件下標控制tab跳轉
  private controller: TabsController = new TabsController()

  // 單獨的頁簽
  @Builder
  Tab(tabNumber: number) {
    Row({ space: 20 }) {
      Text("頁簽 " + tabNumber).fontSize(18)
      Image($r('app.media.ic_public_cancel_filled')).width(20).height(20).onClick(() = > {
        //獲取Tabs組件當前顯示的頁簽中顯示的數字
        let focusNumber = this.tabArray[this.focusIndex]
        //被刪除的頁簽是否是當前選中的頁簽,且是最后一個頁簽
        if (this.focusIndex === this.tabArray.indexOf(tabNumber) && this.focusIndex == this.tabArray.length - 1) {
          //判斷是否需要跳回到創建該頁簽時的頁簽,如果不需要直接跳轉到前一個頁簽
          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
        //對應刪除頁面中的第二種情況
        if (this.tabArray.indexOf(focusNumber) >= 0) {
          this.focusIndex = this.tabArray.indexOf(focusNumber)
        }
        //設置50ms 延遲跳轉
        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() {
        // 頁簽
        // Row() {
        Stack() {
          Row({ space: 7 }) {
            //tabs
            Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
              ForEach(this.tabArray, (item: number) = > {
                TabContent() {
                  Text('我是頁面 ' + item + " 的內容")
                    .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%')
  }
}

本文主要講解在鴻蒙開發當中ArkUI中的增刪Tab頁簽實現,更多的鴻蒙ArkUI學習,可以參考下面的學習曲線圖:

完整版鴻蒙os與openharmony技術路線與文檔,可在主頁保存

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 鴻蒙系統
    +關注

    關注

    183

    文章

    2634

    瀏覽量

    66217
  • 鴻蒙
    +關注

    關注

    57

    文章

    2310

    瀏覽量

    42742
  • OpenHarmony
    +關注

    關注

    25

    文章

    3660

    瀏覽量

    16154
收藏 人收藏

    評論

    相關推薦

    鴻蒙ArkUI開發-Video組件的使用

    以視頻功能為例,在應用開發過程中,我們需要通過ArkUI提供的Video組件為應用增加基礎的視頻播放功能。借助Video組件,我們可以實現視頻的播放功能并控制其播放狀態。常見的視頻播放場景包括觀看網絡上的較為流行的短視頻,也包括
    的頭像 發表于 01-23 16:59 ?1261次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>ArkUI</b><b class='flag-5'>開發</b>-Video組件的使用

    鴻蒙ArkUI開發學習:【渲染控制語法】

    ArkUI開發框架是一套構建 HarmonyOS / OpenHarmony 應用界面的聲明式UI開發框架,它支持程序使用?`if/else`?條件渲染,?`ForEach`?循環渲染以及?`LazyForEach`?懶加載渲染
    的頭像 發表于 04-09 16:40 ?899次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>ArkUI</b><b class='flag-5'>開發</b>學習:【渲染控制語法】

    鴻蒙開發ArkUI-X基礎知識:【ArkUI跨平臺設計總體說明】

    本文檔描述ArkUI開發框架跨平臺運行能力相關的總體技術方案。
    的頭像 發表于 05-24 15:41 ?1494次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b><b class='flag-5'>ArkUI</b>-X基礎知識:【<b class='flag-5'>ArkUI</b>跨平臺設計總體說明】

    鴻蒙開發ArkUI-X基礎知識:【ArkUI代碼工程及構建介紹】

    ArkUI作為OpenHarmony的默認開發框架,在本項目(ArkUI-X)中需要做到一套代碼同時支持多平臺構建,所以會采取共倉開發的方式,部分倉直接指向OpenHarmony相關開
    的頭像 發表于 05-25 16:45 ?1994次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b><b class='flag-5'>ArkUI</b>-X基礎知識:【<b class='flag-5'>ArkUI</b>代碼工程及構建介紹】

    鴻蒙開發-ArkUI框架實戰【日歷應用 】

    在一42個格子上顯示上個月、當前月、下個月的日期,通過日歷應用的開發了解到了ArkUI組件的一些用法,生命周期和數據的加載過程,對之后的應用開發有很大的幫助。
    發表于 01-17 21:37

    OpenHarmony JS UI小型系統實現tab容器的方法

    應用的不同模塊,但在小型系統中沒有提供tab容器,目前的需求是在L1設備上實現類似于tabs
    發表于 04-01 09:45

    鴻蒙閃屏是怎么實現

    安卓閃屏實現可以通過開辟一個新的線程去實現鴻蒙開發是怎么實現的? 有具體代碼參考嗎??本人
    發表于 04-26 10:25

    HDD杭州站?ArkUI開發更靈活

    HTML5面加載特性。 UI開發效率提升:在交互歸一、多態樣式自定義、工具鏈體驗等方面進行了增強和提升,讓開發更靈活。 圖1 ArkUI框架能力集二、聲明式Canvas繪制能力在W
    發表于 08-05 11:33

    編程小白也能快速掌握的ArkUI JS組件開發

    ,Playground中ArkUI JS組件在線預覽又有更新啦~ 以下為本次新增組件一覽: ● tabs: ● stepper:步驟導航器 ● text:文本 ● form:表單 ● picker
    發表于 08-31 11:09

    ArkUI新能力,助力應用開發更便捷

    管理,以及實時界面預覽等相關能力,幫助您提升應用開發效率,并能在多種設備上實現生動而流暢的用戶體驗。隨著HarmonyOS 3.1版本的發布,ArkUI也新增許多能力,助力應用開發更便
    的頭像 發表于 02-15 16:35 ?840次閱讀

    鴻蒙ArkUI開發-Tabs組件的使用

    鴻蒙ArkUI開發-Tabs組件的使用
    的頭像 發表于 01-19 16:01 ?1762次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>ArkUI</b><b class='flag-5'>開發</b>-Tabs組件的使用

    鴻蒙ArkUI開發實戰:eTS版【笑話app】

    制作一款笑話app,使用ArkUI
    的頭像 發表于 03-25 16:04 ?422次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>ArkUI</b><b class='flag-5'>開發</b>實戰:eTS版【笑話app】

    鴻蒙ArkUI:【從代碼到UI顯示的整體渲染流程】

    方舟開發框架(簡稱ArkUI)是鴻蒙開發的UI框架,提供如下兩種開發范式,我們 **只學聲明式開發
    的頭像 發表于 05-13 16:06 ?803次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>ArkUI</b>:【從代碼到UI顯示的整體渲染流程】

    鴻蒙跨平臺框架:【ArkUi-X】創建工程

    鴻蒙推出了鴻ArkUi-X 框架所以就寫個文章分享一下
    的頭像 發表于 05-13 17:48 ?875次閱讀
    <b class='flag-5'>鴻蒙</b>跨平臺框架:【<b class='flag-5'>ArkUi</b>-X】創建工程

    鴻蒙ArkUI-X跨平臺技術:【開發準備】

    本文檔適用于ArkUI跨平臺應用開發的初學者。通過開發環境搭建、應用工程創建、編譯和運行,熟悉ArkUI跨平臺應用開發基本流程。
    的頭像 發表于 05-24 10:40 ?427次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>ArkUI</b>-X跨平臺技術:【<b class='flag-5'>開發</b>準備】