19楞卡、鴻蒙/布局/創(chuàng)建列表 (List)

概述

列表是一種復雜的容器霜运,當列表項達到一定數(shù)量,內容超過屏幕大小時蒋腮,可以自動提供滾動功能淘捡。它適合用于呈現(xiàn)同類數(shù)據(jù)類型或數(shù)據(jù)類型集,例如圖片和文本池摧。在列表中顯示數(shù)據(jù)集合是許多應用程序中的常見要求(如通訊錄焦除、音樂列表、購物清單等)作彤。

使用列表可以輕松高效地顯示結構化膘魄、可滾動的信息。通過在List組件中按垂直或者水平方向線性排列子組件ListItemGroupListItem竭讳,為列表中的行或列提供單個視圖创葡,或使用循環(huán)渲染迭代一組行或列,或混合任意數(shù)量的單個視圖和ForEach結構绢慢,構建一個列表灿渴。List組件支持使用條件渲染、循環(huán)渲染、懶加載等渲染控制方式生成子組件骚露。

布局與約束

列表作為一種容器蹬挤,會自動按其滾動方向排列子組件,向列表中添加組件或從列表中移除組件會重新排列子組件棘幸。
如下圖所示焰扳,在垂直列表中,List按垂直方向自動排列ListItemGroup或ListItem误续。

ListItemGroup用于列表數(shù)據(jù)的分組展示蓝翰,其子組件也是ListItem。ListItem表示單個列表項女嘲,可以包含單個子組件畜份。

List的子組件必須是ListItemGroup或ListItem,ListItem和ListItemGroup必須配合List來使用欣尼。


List.png
布局

List除了提供垂直和水平布局能力爆雹、超出屏幕時可以滾動的自適應延伸能力之外,還提供了自適應交叉軸方向上排列個數(shù)的布局能力愕鼓。

利用垂直布局能力可以構建單列或者多列垂直滾動列表钙态,如下圖所示。


List.png

利用水平布局能力可以是構建單行或多行水平滾動列表菇晃,如下圖所示册倒。

List.png

Grid和WaterFlow也可以實現(xiàn)單列、多列布局磺送,如果布局每列等寬驻子,且不需要跨行跨列布局,相比Gird和WaterFlow估灿,則更推薦使用List崇呵。

約束

列表的主軸方向是指子組件列的排列方向,也是列表的滾動方向馅袁。垂直于主軸的軸稱為交叉軸域慷,其方向與主軸方向相互垂直。

如下圖所示汗销,垂直列表的主軸是垂直方向犹褒,交叉軸是水平方向;水平列表的主軸是水平方向弛针,交叉軸是垂直方向叠骑。

  • 列表的主軸與交叉軸:


    image.png

    如果List組件主軸或交叉軸方向設置了尺寸,則其對應方向上的尺寸為設置值钦奋。

如果List組件主軸方向沒有設置尺寸座云,當List子組件主軸方向總尺寸小于List的父組件尺寸時,List主軸方向尺寸自動適應子組件的總尺寸付材。

如下圖所示朦拖,一個垂直列表B沒有設置高度時,其父組件A高度為200vp厌衔,若其所有子組件C的高度總和為150vp璧帝,則此時列表B的高度為150vp。

  • 列表主軸高度約束示例1(A: List的父組件; B: List組件; C: List的所有子組件)


    image.png

如果子組件主軸方向總尺寸超過List父組件尺寸時富寿,List主軸方向尺寸適應List的父組件尺寸睬隶。

如下圖所示,同樣是沒有設置高度的垂直列表B页徐,其父組件A高度為200vp苏潜,若其所有子組件C的高度總和為300vp,則此時列表B的高度為200vp变勇。

  • 列表主軸高度約束示例2(A: List的父組件; B: List組件; C: List的所有子組件)
    List組件交叉軸方向在沒有設置尺寸時恤左,其尺寸默認自適應父組件尺寸。
image.png

開發(fā)布局

  • 設置主軸方向
    List組件主軸默認是垂直方向搀绣,即默認情況下不需要手動設置List方向飞袋,就可以構建一個垂直滾動列表。

若是水平滾動列表場景链患,將List的listDirection屬性設置為Axis.Horizontal即可實現(xiàn)巧鸭。listDirection默認為Axis.Vertical,即主軸默認是垂直方向麻捻。

List(){
       ListItem(){
         Text('11')
       }
       ListItem(){
         Text('222')
       }
       ListItem(){
          Text('33')
       }
}.listDirection(Axis.Horizontal)
  • 設置交叉軸布局
    List組件的交叉軸布局可以通過lanes和alignListItem屬性進行設置纲仍,lanes屬性用于確定交叉軸排列的列表項數(shù)量,alignListItem用于設置子組件在交叉軸方向的對齊方式贸毕。

List組件的lanes屬性通常用于在不同尺寸的設備自適應構建不同行數(shù)或列數(shù)的列表巷折,即一次開發(fā)、多端部署的場景崖咨,例如歌單列表锻拘。lanes屬性的取值類型是"number | LengthConstrain",即整數(shù)或者LengthConstrain類型击蹲。以垂直列表為例署拟,如果將lanes屬性設為2,表示構建的是一個兩列的垂直列表歌豺,如圖2中右圖所示推穷。lanes的默認值為1,即默認情況下类咧,垂直列表的列數(shù)是1馒铃。

List(){
        ListItem(){
         Text("abc")
        }
        ListItem(){
          Text("def")
        }
        ListItem(){
          Text("jhhh")
        }
}.lanes(2)

當其取值為LengthConstrain類型時蟹腾,表示會根據(jù)LengthConstrain與List組件的尺寸自適應決定行或列數(shù)。

@Entry
@Component
struct EgLanes {
  @State egLanes: LengthConstrain = { minLength: 200, maxLength: 300 }
  build() {
   List(){
        ListItem(){
         Text("abc")
        }
        ListItem(){
          Text("def")
        }
        ListItem(){
          Text("jhhh")
        }
      }.lanes(this.egLanes)
  }
}

例如区宇,假設在垂直列表中設置了lanes的值為{ minLength: 200, maxLength: 300 }娃殖。此時,

  • 當List組件寬度為300vp時议谷,由于minLength為200vp炉爆,此時列表為一列。
  • 當List組件寬度變化至400vp時卧晓,符合兩倍的minLength芬首,則此時列表自適應為兩列。

同樣以垂直列表為例逼裆,當alignListItem屬性設置為ListItemAlign.Center表示列表項在水平方向上居中對齊郁稍。alignListItem的默認值是ListItemAlign.Start,即列表項在列表交叉軸方向上默認按首部對齊胜宇。

List(){
        ListItem(){
          Text("abc1")
        }
        ListItem(){
          Text("def2")
        }
        ListItem(){
          Text("jhhh3")
        }
}.alignListItem(ListItemAlign.Center)

在列表中顯示數(shù)據(jù)

列表視圖垂直或水平顯示項目集合艺晴,在行或列超出屏幕時提供滾動功能,使其適合顯示大型數(shù)據(jù)集合掸屡。在最簡單的列表形式中封寞,List靜態(tài)地創(chuàng)建其列表項ListItem的內容。
由于在ListItem中只能有一個根節(jié)點組件仅财,不支持以平鋪形式使用多個組件狈究。因此,若列表項是由多個組件元素組成的盏求,則需要將這多個元素組合到一個容器組件內或組成一個自定義組件抖锥。

  • 聯(lián)系人案例
    聯(lián)系人列表的列表項中,每個聯(lián)系人都有頭像和名稱碎罚。此時磅废,需要將Image和Text封裝到一個Row容器內。
List() {
        ListItem() {
          Row() {
            Image('https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png')
              .width(40)
              .height(40)
              .margin(10)

            Text('小明')
              .fontSize(20)
          }
        }

        ListItem() {
          Row() {
            Image('https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png')
              .width(40)
              .height(40)
              .margin(10)

            Text('小紅')
              .fontSize(20)
          }
        }
}

迭代列表內容

通常荆烈,應用通過數(shù)據(jù)集合動態(tài)地創(chuàng)建列表拯勉。使用循環(huán)渲染可從數(shù)據(jù)源中迭代獲取數(shù)據(jù),并在每次迭代過程中創(chuàng)建相應的組件憔购,降低代碼復雜度宫峦。

ArkTS通過ForEach提供了組件的循環(huán)渲染能力。以簡單形式的聯(lián)系人列表為例玫鸟,將聯(lián)系人名稱和頭像數(shù)據(jù)以Contact類結構存儲到contacts數(shù)組导绷,使用ForEach中嵌套ListItem的形式來代替多個平鋪的、內容相似的ListItem屎飘,從而減少重復代碼妥曲。

@State nameArray: string[] = ['張三', '李四', '王五', '趙六']
...
List(){
        ForEach(this.nameArray, (item: string, index: number)=>{
          ListItem(){
            Text(item + ' == ' + index.toString())
          }
        })
}

在List組件中贾费,F(xiàn)orEach除了可以用來循環(huán)渲染ListItem,也可以用來循環(huán)渲染ListItemGroup檐盟。ListItemGroup的循環(huán)渲染詳細使用請參見支持分組列表褂萧。

自定義列表樣式

  • 設置內容間距
    在初始化列表時,如需在列表項之間添加間距遵堵,可以使用space參數(shù)箱玷。例如怨规,在每個列表項之間沿主軸方向添加10vp的間距:
@State nameArray: string[] = ['張三', '李四', '王五', '趙六']
....
List({ space: 10 }){
        ForEach(this.nameArray, (item: string, index: number)=>{
          ListItem(){
            Text(item + ' == ' + index.toString())
          }
        })
}
  • 添加分隔線
    分隔線用來將界面元素隔開陌宿,使單個元素更加容易識別。如下圖所示波丰,當列表項左邊有圖標(如藍牙圖標)壳坪,由于圖標本身就能很好的區(qū)分,此時分隔線從圖標之后開始顯示即可掰烟。
    List提供了divider屬性用于給列表項之間添加分隔線爽蝴。在設置divider屬性時,可以通過strokeWidth和color屬性設置分隔線的粗細和顏色纫骑。
    startMargin和endMargin屬性分別用于設置分隔線距離列表側邊起始端的距離和距離列表側邊結束端的距離蝎亚。
class DividerTmp {
  strokeWidth: Length = 1
  startMargin: Length = 60
  endMargin: Length = 10
  color: ResourceColor = '#ffe9f0f0'

  constructor(strokeWidth: Length, startMargin: Length, endMargin: Length, color: ResourceColor) {
    this.strokeWidth = strokeWidth
    this.startMargin = startMargin
    this.endMargin = endMargin
    this.color = color
  }
}

....

@State egDivider: DividerTmp = new DividerTmp(1, 60, 10, '#ffe9f0f0')
....
//
List({ space: 10 }){
        ForEach(this.nameArray, (item: string, index: number)=>{
          ListItem(){
            Text(item + ' == ' + index.toString())
          }
        })
}.divider(this.egDivider)
  • 添加滾動條
    當列表項高度(寬度)超出屏幕高度(寬度)時,列表可以沿垂直(水平)方向滾動先馆。在頁面內容很多時发框,若用戶需快速定位,可拖拽滾動條煤墙,在使用List組件時梅惯,可通過scrollBar屬性控制列表滾動條的顯示。scrollBar的取值類型為BarState仿野,當取值為BarState.Auto表示按需顯示滾動條铣减。此時,當觸摸到滾動條區(qū)域時顯示控件脚作,可上下拖拽滾動條快速瀏覽內容葫哗,拖拽時會變粗。若不進行任何操作球涛,2秒后滾動條自動消失魄梯。
    scrollBar屬性API version 9及以下版本默認值為BarState.Off,從API version 10版本開始默認值為BarState.Auto宾符。
List({ space: 10 }){
        ForEach(this.nameArray, (item: string, index: number)=>{
          ListItem(){
            Text(item + ' == ' + index.toString())
          }
        })
}.divider(this.egDivider).scrollBar(BarState.Auto)

支持分組列表

在列表中支持數(shù)據(jù)的分組展示酿秸,可以使列表顯示結構清晰,查找方便魏烫,從而提高使用效率辣苏。在List組件中使用ListItemGroup對項目進行分組肝箱,可以構建二維列表。在List組件中可以直接使用一個或者多個ListItemGroup組件稀蟋,ListItemGroup的寬度默認充滿List組件煌张。在初始化ListItemGroup時,可通過header參數(shù)設置列表分組的頭部組件退客。

// 分組列表
@Builder itemHead(text: string) {
    // 列表分組的頭部組件骏融,對應聯(lián)系人分組A、B等位置的組件
    Text(text)
      .fontSize(20)
      .backgroundColor('#fff1f3f5')
      .width('100%')
      .padding(5)
}
...
 List(){
        ListItemGroup({ header: this.itemHead('A') }){
          ListItem(){
            Text("A1")
          }
          ListItem(){
            Text("A2")
          }
          ListItem(){
            Text("A3")
          }
        }

        ListItemGroup({ header: this.itemHead('B') }){
          ListItem(){
            Text("B1")
          }
          ListItem(){
            Text("B2")
          }
          ListItem(){
            Text("B3")
          }
        }

}

如果多個ListItemGroup結構類似萌狂,可以將多個分組的數(shù)據(jù)組成數(shù)組档玻,然后使用ForEach對多個分組進行循環(huán)渲染。例如在聯(lián)系人列表中茫藏,將每個分組的聯(lián)系人數(shù)據(jù)contacts(可參考迭代列表內容章節(jié))和對應分組的標題title數(shù)據(jù)進行組合误趴,定義為數(shù)組contactsGroups。然后在ForEach中對contactsGroups進行循環(huán)渲染务傲,即可實現(xiàn)多個分組的聯(lián)系人列表凉当。可參考添加粘性標題章節(jié)示例代碼售葡。

添加粘性標題

粘性標題是一種常見的標題模式看杭,常用于定位字母列表的頭部元素。如下圖所示挟伙,在聯(lián)系人列表中滾動A部分時楼雹,B部分開始的頭部元素始終處于A的下方。而在開始滾動B部分時像寒,B的頭部會固定在屏幕頂部烘豹,直到所有B的項均完成滾動后,才被后面的頭部替代诺祸。

粘性標題不僅有助于闡明列表中數(shù)據(jù)的表示形式和用途携悯,還可以幫助用戶在大量信息中進行數(shù)據(jù)定位,從而避免用戶在標題所在的表的頂部與感興趣區(qū)域之間反復滾動筷笨。

List組件的sticky屬性配合ListItemGroup組件使用憔鬼,用于設置ListItemGroup中的頭部組件是否呈現(xiàn)吸頂效果或者尾部組件是否呈現(xiàn)吸底效果。

通過給List組件設置sticky屬性為StickyStyle.Header胃夏,即可實現(xiàn)列表的粘性標題效果轴或。如果需要支持吸底效果,可以通過footer參數(shù)初始化ListItemGroup的底部組件仰禀,并將sticky屬性設置為StickyStyle.Footer照雁。

List(){
        ForEach(this.nameArray, (item: string, index: number)=>{
          ListItemGroup({ header: this.itemHead('A') }){
            ListItem(){
              Text("A1")
            }
            ListItem(){
              Text("A2")
            }
            ListItem(){
              Text("A3")
            }
          }
        })


}.sticky(StickyStyle.Header)

控制滾動位置

控制滾動位置在實際應用中十分常見,例如當新聞頁列表項數(shù)量龐大答恶,用戶滾動列表到一定位置時饺蚊,希望快速滾動到列表底部或返回列表頂部萍诱。此時,可以通過控制滾動位置來實現(xiàn)列表的快速定位污呼。
List組件初始化時裕坊,可以通過scroller參數(shù)綁定一個Scroller對象,進行列表的滾動控制燕酷。例如籍凝,用戶在新聞應用中,點擊新聞頁面底部的返回頂部按鈕時苗缩,就可以通過Scroller對象的scrollToIndex方法使列表滾動到指定的列表項索引位置饵蒂。

首先,需要創(chuàng)建一個Scroller的對象listScroller挤渐。

private listScroller: Scroller = new Scroller();

然后苹享,通過將listScroller用于初始化List組件的scroller參數(shù)双絮,完成listScroller與列表的綁定浴麻。在需要跳轉的位置指定scrollToIndex的參數(shù)為0,表示返回列表頂部敦跌。

Stack({ alignContent: Alignment.Bottom }) {
  // 將listScroller用于初始化List組件的scroller參數(shù)旧乞,完成listScroller與列表的綁定植兰。
  List({ space: 20, scroller: this.listScroller }) {
    // ...
  }

  Button() {
    // ...
  }
  .onClick(() => {
    // 點擊按鈕時,指定跳轉位置膏萧,返回列表頂部
    this.listScroller.scrollToIndex(0)
  })
}
List.png
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
禁止轉載,如需轉載請通過簡信或評論聯(lián)系作者蝌衔。
  • 序言:七十年代末榛泛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子噩斟,更是在濱河造成了極大的恐慌曹锨,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剃允,死亡現(xiàn)場離奇詭異沛简,居然都是意外死亡,警方通過查閱死者的電腦和手機斥废,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門椒楣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人牡肉,你說我怎么就攤上這事捧灰。” “怎么了统锤?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵毛俏,是天一觀的道長吩屹。 經(jīng)常有香客問我,道長拧抖,這世上最難降的妖魔是什么煤搜? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮唧席,結果婚禮上擦盾,老公的妹妹穿的比我還像新娘。我一直安慰自己淌哟,他們只是感情好迹卢,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著徒仓,像睡著了一般腐碱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上掉弛,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天症见,我揣著相機與錄音,去河邊找鬼殃饿。 笑死谋作,一個胖子當著我的面吹牛,可吹牛的內容都是我干的乎芳。 我是一名探鬼主播遵蚜,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼奈惑!你這毒婦竟也來了吭净?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤肴甸,失蹤者是張志新(化名)和其女友劉穎寂殉,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雷滋,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡不撑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了晤斩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片焕檬。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖澳泵,靈堂內的尸體忽然破棺而出实愚,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布腊敲,位于F島的核電站击喂,受9級特大地震影響,放射性物質發(fā)生泄漏碰辅。R本人自食惡果不足惜懂昂,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望没宾。 院中可真熱鬧凌彬,春花似錦、人聲如沸循衰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽会钝。三九已至伐蒋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間迁酸,已是汗流浹背先鱼。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留胁出,地道東北人型型。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓段审,卻偏偏與公主長得像全蝶,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子寺枉,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內容