HarmonyOS 鸿蒙Next 纵横向联动List开发心得

HarmonyOS 鸿蒙Next 纵横向联动List开发心得

  • 介绍

本开发心得主要实现List组件绑定Scroller滚动控制器和LazyForEach数据懒加载实现横纵列表联动,该场景多用于参数对比、信息对比等。

  • 效果图预览

  • 使用说明
  1. 纵向滑动列表,内容和行标题保持联动
  2. 横向滑动列表,内容和列标题保持联动
  3. 上划时,列表头标题吸附在顶部
  4. 删除时,更新数据及标题
  5. 相同参数项与不同参数项分为不同背景色
  6. 隐藏相同时,将相同参数项隐藏
  • 实现思路
  1. 数据结构,先将获取到的数据整理为如下数据结构showdata列表
    // 页面展示数据类型
    export class ShowData {
    // 对应基本参数,动力参数等小标题
    name: string = ‘’;
    // 厂商,价格等信息数组
    itemlist: PartInfo[] = [];
    // 每一个部件对应的控制器数组,与详细参数一一对应
    scrollerArray: Scroller[] = [];
    }
    // 所有车型部件对应的详细参数信息
    export class PartInfo {	
    // 价格,厂商等标题信息
    name: string = ‘’;
    // 每个标题对应的数值列表
    valuelist: string[] = [];
    }

  2. LazyForEach加载数据
    LazyForEach(this.dataSource, (item: ShowData, index: number) => {
    ListItemGroup({ header: this.leftFixedTitle(item.name) }) {
    this.bottomLeftListItem(item);
    }
    }, (item: ShowData, index: number) => item.name + index)

  3. 顶部列表、底部左侧列表、底部右侧列表布局
    Column() {
    this.topComponent(this.carType.length);
    Row() {
    this.bottomLeftComponent();
    this.bottomRightComponent();
    }
    .height(‘calc(100% - 100vp)’)
    }

  4. 底部右侧列表每一行绑定一个Scroll对象
    showData.itemlist.forEach(element => {
    let scroller: Scroller = new Scroller();
    showData.scrollerArray.push(scroller);
    })
    this.showDataArray.push(showData);

  5. 顶部绑定TopListScroller,列表横向滑动时,让底部右侧控制器同步滚动,实现联动
      .onScrollFrameBegin((offset: number, state: ScrollState) => {
    // 顶部列标题列表滚动时,让每一行的滚动控制器保持同步滚动,实现联动
    this.showDataArray.forEach((showData: ShowData) => {
    showData.scrollerArray.forEach((scroller: Scroller) => {
    // 偏移量为顶部列表滚动控制器当前偏移量+本次滚动的偏移量
    scroller.scrollTo({ xOffset: this.topListScroller.currentOffset().xOffset + offset, yOffset: 0 });
    });
    });
    return { offsetRemain: offset };
    })

  6. 底部左侧列表绑定bottomLeftListScroll,列表纵向滚动式,通过控制bottomRightListScroller的滚动偏移量实现联动
    .onScrollFrameBegin((offset: number, state: ScrollState) => {
    // 通过控制右下列表的滚动控制器来保持和左下列表的联动
    this.bottomRightListScroller.scrollTo({
    xOffset: 0,
    // 滚动偏移量为左下列表滚动控制器的当前偏移量+本次滚动的的偏移量
    yOffset: this.bottomLeftListScroller.currentOffset().yOffset + offset
    });
    return { offsetRemain: offset };
    })

  7. 底部右侧列表绑定bottomRightListScroller,列表纵向滚动时,通过控制bottomLeftListScroll的滚动偏移量实现纵向列表联动。列表纵向滚动时,让每一行的滚动控制器的滚动偏移量都保持一致,实现联动。通过父子传值(initOffset),使每一行展示内容的初始偏移量保持一致。
    scrollCallback: (value) => {
    // 顶部车型列表保持联动
    this.topListScroller.scrollTo({ xOffset: value, yOffset: 0 });
    this.showDataArray.forEach((showData: ShowData) => {
    // 通过scroller数组保持联动
    showData.scrollerArray.forEach((scroller: Scroller) => {
    if (scroller !== item.scrollerArray[key]) {
    scroller.scrollTo({ xOffset: value, yOffset: 0 });
    }
    })
    })
    },
    // 展示内容横向滚动时,实时传回滚动偏移量
    remainOffsetCallback: (value) => {
    this.remainOffset = value;
    }
    .onScrollFrameBegin((offset: number, scrollState: ScrollState) => { if (this.scrollCallback) { // 传递滚动偏移量 this.scrollCallback(this.scroller!.currentOffset().xOffset + offset); } return { offsetRemain: offset }; }) .onDidScroll((scrollOffset: number, scrollState: ScrollState) => { if (this.remainOffsetCallback) { // 更新滚动偏移量 this.remainOffsetCallback(this.scroller!.currentOffset().xOffset); } })

  8. 底部右侧列表横向滚动时每一行内容都绑定一个Scroller对象,列表滚动时,通过传参,传递滚动偏移量,使每一行的滚动偏移量都保持一致。
    .onDidScroll((scrollOffset: number, scrollState: ScrollState) => {
    // 行标题列表纵向滚动时,下方右侧的每一行展示内容的横向偏移量保持一致
    this.showDataArray.forEach((showData: ShowData) => {
    showData.scrollerArray.forEach((scroller: Scroller) => {
    scroller.scrollTo({ xOffset: this.remainOffset, yOffset: 0 });
    })
    });
    })

  9. 头部标题删除时,同步删除每一列数据的数据值,多次删除时列表的index值不变会发生bug
    .onClick(() => {
    // 删除数据中的这一列数据
    if(this.carType.length === 1){
    return
    }
    // 重新找到此项数据的角标,不执行这一步,多次删除会出错
    let index = this.carType.findIndex(a => a === item)
    this.carType.splice(index,1)
    this.showDataArray.forEach(item => {
    item.itemlist.forEach(a => {
    a.valuelist.splice(index,1)
    })
    })
    })

  10. 将参数值相同的列设为不同背景色,并打开隐藏相同时隐藏掉参数相同项。
    getVisibility(itemInfo: PartInfo): Visibility{
    let isSame = ArrayUtil.respectivelyIdentical(itemInfo.valuelist)
    return isSame&&this.isConcealSame?Visibility.None:Visibility.Visible
    }
    /**

    • 判断数组中的元素是否都相同
    • param 数组对象Array<Object> 含有的对象Object
    • @returns boolean */ static respectivelyIdentical(array: Array<Object>): boolean { try { for (let index = 1; index < array.length; index++) { const element = array[index]; if (element !== array[0]) { return false; } } return true } catch (err) { // logger.error('Failed ’ + JSON.stringify(err)) return false; } }

  • 高性能知识点

        ​  本示例数据量较少的列表,使用ForEach加载List数据,数据量较多的列使用了LazyForEach进行数据懒加载。

    本示例的滑动过程帧率可以达到满帧(120帧),trace截图如下所示:

  • 参考资料
  1. List: https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-list-0000001862607449
  2. Scroll: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-container-scroll-V5#onscrolldeprecated
  3. LazyForEach: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/arkts-rendering-control-lazyforeach-0000001524417213-V2


更多关于HarmonyOS 鸿蒙Next 纵横向联动List开发心得的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS 鸿蒙Next 纵横向联动List开发心得的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


HarmonyOS 鸿蒙Next 纵横向联动List开发心得

在HarmonyOS鸿蒙Next平台上进行纵横向联动List的开发时,主要挑战在于如何高效地处理列表的滚动和联动逻辑。通过鸿蒙系统提供的ArkUI框架,开发者可以利用其丰富的组件和API来实现这一功能。

在纵向列表的基础上,嵌套横向列表以形成联动效果,关键在于数据绑定和事件处理。鸿蒙系统支持数据双向绑定,使得列表项的更新变得更为简洁。通过监听纵向列表的滚动事件,可以动态调整横向列表的显示内容,实现联动效果。

此外,鸿蒙系统对性能优化有着良好的支持。在开发过程中,可以利用鸿蒙提供的性能分析工具,对列表的渲染和滚动性能进行调优,确保用户体验的流畅性。

需要注意的是,鸿蒙系统的UI组件和API与Android和iOS有所不同,开发者需要熟悉鸿蒙系统的开发文档和组件库,以便更好地利用系统特性。

在开发过程中,可能会遇到一些特定于鸿蒙系统的问题,如组件的适配、事件的分发等。此时,可以参考鸿蒙系统的官方文档或社区资源来寻找解决方案。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。在这里,你可以获得专业的技术支持和解决方案。

回到顶部