开天辟地 HarmonyOS(鸿蒙) - 组件(列表类): List(列表基础)

源码 https://github.com/webabcd/HarmonyDemo
作者 webabcd

开天辟地 HarmonyOS(鸿蒙) - 组件(列表类): List(列表基础)

示例如下:

pages\component\list\ListDemo.ets

/*
 * List - 列表基础
 *
 * 注:List 是一个可滚动组件,相关特性请参见 /component/layout/ScrollDemo.ets 中的说明
 */

import { TitleBar } from '../../TitleBar';
import { ComposeListItem, IconType, LengthMetrics, promptAction } from '@kit.ArkUI';

@Entry
@Component
struct ListDemo {

  build() {
    Column() {
      TitleBar()
      Tabs() {
        TabContent() { MySample1() }.tabBar('基础1').align(Alignment.Top)
        TabContent() { MySample2() }.tabBar('基础2').align(Alignment.Top)
        TabContent() { MySample3() }.tabBar('ComposeListItem').align(Alignment.Top)
        TabContent() { MySample4() }.tabBar('多行多列').align(Alignment.Top)
        TabContent() { MySample5() }.tabBar('ListScroller 相关').align(Alignment.Top)
      }
      .scrollable(true)
      .barMode(BarMode.Scrollable)
      .layoutWeight(1)
    }
  }
}

@Component
struct MySample1 {

  @State message: string = ""

  private array: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

  build() {
    Stack({ alignContent: Alignment.TopStart }) {
      /*
       * List - 列表
       *   space - 主轴方向上每个 item 之间的间隔距离
       *   initialIndex - 初始时,定位到指定索引位置的 item
       *   listDirection() - item 们的排列方向(Axis.Vertical 或 Axis.Horizontal)
       *   chainAnimation() - 拖动时是否启用链式联动效果
       *     手指拖动过程中,手指拖动的 ListItem 会驱动相邻的 ListItem 做弹簧联动效果(前提是必须是单列模式,且边缘效果为 EdgeEffect.Spring 时)
       *   onScrollIndex() - item 滚入或滚出可视区时,或者可视区中间显示的 item 发生变化时的回调
       *     start - 可视区内第一个 item 的索引位置
       *     end - 可视区内最后一个 item 的索引位置
       *     center - 可视区内中间 item 的索引位置
       *
       * ListItem - list 内的每个 item
       */
      List({
        space: 20,
        initialIndex: 3,
      }) {
        ForEach(this.array, (item: number) => {
          ListItem() {
            Text(item.toString()).width('100%').height(100)
              .fontSize(48).textAlign(TextAlign.Center)
              .backgroundColor(Color.Orange).borderRadius(20)
          }
          .margin({ left: 20, right: 20 })
        })
      }
      .listDirection(Axis.Vertical)
      .chainAnimation(true)
      .edgeEffect(EdgeEffect.Spring)
      .onScrollIndex((start: number, end: number, center: number) => {
        this.message = `onScrollIndex start:${start}, end:${end}, center:${center}`
      })
      .width('100%')
      .height('100%')

      Text(this.message).fontSize(16).fontColor(Color.White).backgroundColor(Color.Blue)
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Yellow)
  }
}

@Component
struct MySample2 {

  private array: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

  // 实例化 ChildrenMainSize,并指定主轴方向上的默认大小
  childrenMainSize: ChildrenMainSize = new ChildrenMainSize(100)
  aboutToAppear(){
    // 位置 3, 4, 5, 6 的 item 的大小全部指定为 200
    this.childrenMainSize.splice(3, 4, [200, 200, 200, 200])
    // 位置 9 的 item 的大小指定为 200
    this.childrenMainSize.update(9, 200)
  }

  build() {
    Column() {
      /*
       * List - 列表
       *   divider() - 每个 item 之间的分隔线
       *     strokeWidth - 分隔线的画笔宽度
       *     color - 颜色
       *     startMargin - 左侧外边距
       *     endMargin - 右侧外边距
       *     注:当 chainAnimation(true) 时不会显示分隔线
       *   contentStartOffset() - 顶部 item 与顶部边缘之间的间距
       *   contentEndOffset() - 底部 item 与底部边缘之间的间距
       *   childrenMainSize() - 指定每个 item 的主轴方向上的不同的大小
       *     value - 主轴方向上的默认大小
       *     splice(), update() - 更新不同位置的 item 的主轴方向上的大小
       *     注:当每个 item 在轴方向上的大小不一致时,需要额外通过此方式指定他们的大小,这样在调用 scrollToIndex(), scrollTo(), currentOffset() 等时才不会有问题
       */
      List({ space: 20 }) {
        ForEach(this.array, (item: number) => {
          ListItem() {
            Text(item.toString()).width('100%')
              .fontSize(48).textAlign(TextAlign.Center)
              .backgroundColor(Color.Orange).borderRadius(20)
              .height((item >= 3 && item < 7) || (item == 9) ? 200 : 100)
          }
          .margin({ left: 20, right: 20 })
        })
      }
      .divider({
        strokeWidth: 2,
        color: Color.Red,
        startMargin: 20,
        endMargin: 20
      })
      .contentStartOffset(50)
      .contentEndOffset(50)
      .childrenMainSize(this.childrenMainSize)
      .width('100%')
      .height('100%')
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Yellow)
  }
}

@Component
struct MySample3 {
  build() {
    Column() {
      List({ space: 10 }) {
        /*
         * ComposeListItem - 增加了一些内置功能的 ListItem
         *   contentItem - 中间及左侧的内容
         *   operateItem - 右侧的内容
         */
        ComposeListItem({
          contentItem: ({
            iconStyle: IconType.HEAD_SCULPTURE, // 用于指定图标的大小
            icon: $r('app.media.app_icon'),
            primaryText: 'primaryText',
            secondaryText: 'secondaryText',
            description: 'description'
          }),
          operateItem: ({
            icon: {
              value: $r('app.media.ic_settings'),
              action: () => {
                promptAction.showToast({ message: 'icon clicked' });
              }
            },
            text: 'text'
          })
        })
        ComposeListItem({
          operateItem: ({
            arrow: { value: $r('app.media.ic_arrow_right'), action: () => { } },
            text: 'text'
          })
        })
        ComposeListItem({
          operateItem: ({
            switch: { isCheck: true, onChange: (value: boolean) => { } },
          })
        })
        ComposeListItem({
          operateItem: ({
            checkbox: { isCheck: false, onChange: (value: boolean) => { } },
          })
        })
        ComposeListItem({
          operateItem: ({ image: $r('app.media.ic_settings') })
        })
      }
    }
  }
}

@Component
struct MySample4 {

  private array: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

  build() {
    Column({ space:20 }) {
      /*
       * List - 列表
       *   lanes() - 多行多列的配置,以下以 listDirection(Axis.Vertical) 为例
       *     value - 列数
       *       可以指定一个整数,用于指定列数
       *       可以指定一个 LengthConstrain 对象,用于动态计算列数
       *         minLength - 最小列宽
       *         maxLength - 最大列宽
       *     gutter - 列间距
       *   alignListItem() - 水平方向上的对齐方式(ListItemAlign 枚举),当 lanes() 指定为 LengthConstrain 对象时有效
       *     Start, Center, End
       */
      List({ space: 20 }) {
        ForEach(this.array, (item: number) => {
          ListItem() {
            Text(item.toString())
              .width('100%').height(100).fontSize(24).textAlign(TextAlign.Center)
          }
          .border({ width: 2, color: Color.Green })
        })
      }
      .height(300)
      .width("80%")
      .borderWidth(2)
      .borderColor(Color.Red)
      .scrollBar(BarState.Off)
      .lanes(3, 10)

      List({ space: 20 }) {
        ForEach(this.array, (item: number) => {
          ListItem() {
            Text(item.toString())
              .width('100%').height(100).fontSize(24).textAlign(TextAlign.Center)
          }
          .border({ width: 2, color: Color.Green })
        })
      }
      .height(300)
      .width("80%")
      .borderWidth(2)
      .borderColor(Color.Red)
      .scrollBar(BarState.Off)
      .lanes({
        minLength: 50,
        maxLength: 50,
      }, 10)
      .alignListItem(ListItemAlign.End)
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Yellow)
  }
}

@Component
struct MySample5 {

  @State message: string = ""

  /*
   * ListScroller 是一个 controller,是用于和 List 交互的,声明式编程通常都会用这种方式
   * ListScroller 继承自 Scroller(请参见 /component/layout/ScrollDemo.ets 中的说明)
   */
  listScroller: ListScroller = new ListScroller()
  private array: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

  build() {
    Stack({ alignContent: Alignment.TopStart }) {
      /*
       * List - 列表
       *   scroller - 指定 List 需要绑定的 ListScroller
       */
      List({ scroller: this.listScroller }) {
        ForEach(this.array, (item: number) => {
          ListItem() {
            Text(item.toString()).width('100%').height(200)
              .fontSize(48).textAlign(TextAlign.Center)
              .backgroundColor(Color.Orange).borderRadius(20)
          }
          .margin(10)
        })
      }
      .width('100%')
      .height('100%')

      Column({space:10}) {

        /*
         * ListScroller - 用于和绑定的 List 之间的交互(继承自 Scroller)
         *   scrollToIndex() - 滚动到指定索引位置的 item(仅 Grid, List, WaterFlow 有效)
         *     value - 需要滚动到的 item 的索引位置
         *     smooth - 是否平滑滚动
         *     align - 滚动到的 item 与可视区的对齐方式(ScrollAlign 枚举)
         *       START - item 与可视区的顶端对齐
         *       CENTER - item 与可视区的中间对齐
         *       END - item 与可视区的底端对齐
         *     options - 选项
         *       extraOffset - 在当前位置上的偏移距离
         *   getItemRect() - 获取指定索引位置的 item 的位置和大小(仅 Grid, List, WaterFlow 有效)
         *     返回值包括 x, y, width, height
         *     注:指定的 item 必须要显示在可视区才能获取到正确的值,否则返回的都是 0
         */

        Button('scrollToIndex')
          .onClick(() => {
            this.listScroller.scrollToIndex(
              5,
              true,
              ScrollAlign.START,
              {
                extraOffset: LengthMetrics.vp(0)
              })
          })
        Button('getItemRect(3)')
          .onClick(() => {
            const itemRect = this.listScroller.getItemRect(3)
            this.message = `getItemRect(3) x:${itemRect.x}, y:${itemRect.y}, width:${itemRect.width}, height:${itemRect.height}`
          })

        Text(this.message).fontSize(16).fontColor(Color.White).backgroundColor(Color.Blue)
      }
      .hitTestBehavior(HitTestMode.None)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Yellow)
  }
}

源码 https://github.com/webabcd/HarmonyDemo
作者 webabcd

posted @ 2025-02-06 08:39  webabcd  阅读(129)  评论(0)    收藏  举报