当前位置: 首页 > article >正文

17 HarmonyOS NEXT UVList组件开发指南(四)

温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦!

HarmonyOS NEXT UVList组件开发指南(四)

在这里插入图片描述

文章目录

  • HarmonyOS NEXT UVList组件开发指南(四)
    • 第四篇:UVList组件高级特性与性能优化
      • 1. 高级特性
        • 1.1 自定义渲染
        • 1.2 分组列表
        • 1.3 可展开列表
      • 2. 性能优化
        • 2.1 状态管理优化
        • 2.2 渲染性能优化
        • 2.3 条件渲染优化
      • 3. 内存优化
        • 3.1 资源复用
        • 3.2 图片资源优化
      • 4. 交互优化
        • 4.1 点击反馈优化
        • 4.2 手势交互优化
        • 4.3 动画效果优化
      • 5. 总结与最佳实践

第四篇:UVList组件高级特性与性能优化

1. 高级特性

1.1 自定义渲染

除了使用默认的渲染方式外,UVList组件还支持自定义渲染,以满足更复杂的UI需求:

@Entry
@Component
struct CustomRenderDemo {
    @State listItems: Array<ListItemProps> = [
        {
            title: '自定义项1',
            note: '自定义渲染示例'
        },
        {
            title: '自定义项2',
            note: '自定义渲染示例'
        }
    ];
    
    // 自定义渲染函数
    @Builder
    private renderCustomItem(item: ListItemProps) {
        Row() {
            Circle({ width: 8, height: 8 })
                .fill('#2979ff')
                .margin({ right: 8 })
                
            Column() {
                Text(item.title)
                    .fontSize(16)
                    .fontWeight(FontWeight.Medium)
                
                if (item.note) {
                    Text(item.note)
                        .fontSize(14)
                        .fontColor('#999')
                        .margin({ top: 4 })
                }
            }
            .alignItems(HorizontalAlign.Start)
        }
        .width('100%')
        .padding(16)
        .backgroundColor(Color.White)
        .borderRadius(8)
    }
    
    build() {
        Column() {
            // 使用自定义渲染的列表
            List() {
                ForEach(this.listItems, (item: ListItemProps) => {
                    ListItem() {
                        this.renderCustomItem(item)
                    }
                    .padding({ left: 16, right: 16, top: 4, bottom: 4 })
                })
            }
            .width('100%')
            .divider({ strokeWidth: 1, color: '#f5f5f5', startMargin: 16, endMargin: 16 })
            .borderRadius(8)
            .backgroundColor(Color.White)
        }
        .width('100%')
        .height('100%')
        .backgroundColor('#f5f5f5')
        .padding(16)
    }
}
1.2 分组列表

通过扩展UVList组件,可以实现分组列表功能:

// 分组列表数据接口
interface GroupListProps {
    // 分组标题
    title?: string;
    // 分组数据
    groups: Array<{
        // 分组标题
        title: string;
        // 分组项
        items: Array<ListItemProps>;
    }>;
}

@Component
struct GroupList {
    private props: GroupListProps = {} as GroupListProps;
    
    build() {
        Column() {
            // 列表标题(如果有)
            if (this.props.title) {
                Text(this.props.title)
                    .fontSize(18)
                    .fontWeight(FontWeight.Bold)
                    .width('100%')
                    .textAlign(TextAlign.Start)
                    .padding({ left: 16, right: 16, top: 16, bottom: 8 })
            }
            
            // 遍历分组
            ForEach(this.props.groups, (group, groupIndex) => {
                Column() {
                    // 分组标题
                    Text(group.title)
                        .fontSize(16)
                        .fontWeight(FontWeight.Medium)
                        .width('100%')
                        .textAlign(TextAlign.Start)
                        .padding({ left: 16, right: 16, top: 16, bottom: 8 })
                    
                    // 分组内容
                    UVList({
                        props: {
                            items: group.items
                        }
                    })
                }
                .margin({ top: groupIndex > 0 ? 16 : 0 })
            })
        }
        .width('100%')
    }
}
1.3 可展开列表

通过扩展UVList组件,可以实现可展开列表功能:

// 可展开列表项接口
interface ExpandableListItemProps extends ListItemProps {
    // 子项
    children?: Array<ListItemProps>;
    // 是否展开
    expanded?: boolean;
}

@Component
struct ExpandableListItem {
    @ObjectLink item: ExpandableListItemProps;
    
    build() {
        Column() {
            // 主项
            Row() {
                // 标题
                Text(this.item.title)
                    .fontSize(16)
                    .fontWeight(FontWeight.Medium)
                    .layoutWeight(1)
                
                // 展开/收起图标
                Image(this.item.expanded ? $r('app.media.ic_arrow_up') : $r('app.media.ic_arrow_down'))
                    .width(16)
                    .height(16)
                    .objectFit(ImageFit.Contain)
            }
            .width('100%')
            .padding(16)
            .backgroundColor(Color.White)
            .borderRadius(8)
            .onClick(() => {
                // 切换展开状态
                this.item.expanded = !this.item.expanded;
            })
            
            // 子项(如果展开)
            if (this.item.expanded && this.item.children) {
                Column() {
                    ForEach(this.item.children, (child: ListItemProps) => {
                        UVListItem({
                            item: child,
                            showIcon: true,
                            showRightText: true,
                            navigable: true
                        })
                    })
                }
                .padding({ left: 16 })
            }
        }
        .width('100%')
    }
}

2. 性能优化

2.1 状态管理优化
// 优化前:整个列表数据作为响应式状态
@State listItems: Array<ListItemProps> = [];

// 优化后:将不变的数据与变化的状态分离
private listItemsData: Array<{
    id: string;
    title: string;
    note: string;
    icon?: string | Resource;
}> = [];

@State private listItemsState: Record<string, {
    disabled: boolean;
    expanded: boolean;
}> = {};

// 构建列表项
private getListItems(): Array<ListItemProps> {
    return this.listItemsData.map(item => ({
        ...item,
        disabled: this.listItemsState[item.id]?.disabled || false,
        onClick: () => this.handleItemClick(item.id)
    }));
}

优化说明:

  1. 将不变的数据(如标题、描述、图标)与变化的状态(如禁用状态、展开状态)分离
  2. 减少响应式数据的体积,提高性能
  3. 按需构建列表项,避免不必要的更新
2.2 渲染性能优化
// 优化前:直接在ForEach中渲染所有列表项
ForEach(this.listItems, (item: ListItemProps) => {
    ListItem() {
        UVListItem({
            item: item,
            // 其他属性
        })
    }
})

// 优化后:使用LazyForEach按需渲染列表项
LazyForEach(new DataSource(this.listItems), (item: ListItemProps) => {
    ListItem() {
        UVListItem({
            item: item,
            // 其他属性
        })
    }
}, item => item.id)

优化说明:

  1. 使用LazyForEach代替ForEach,实现按需渲染
  2. 只渲染可见区域的列表项,减少内存占用和提高渲染性能
  3. 为每个列表项提供唯一的key,优化更新性能
2.3 条件渲染优化
// 优化前:频繁的条件判断
build() {
    Row() {
        if (this.showIcon && this.item.icon) {
            // 渲染图标
        }
        
        Column() {
            Text(this.item.title)
            
            if (this.item.note) {
                Text(this.item.note)
            }
        }
        
        Row() {
            if (this.showRightText && this.item.rightText) {
                Text(this.item.rightText)
            }
            
            if (this.navigable && this.item.showArrow !== false) {
                Image($r('app.media.ic_arrow_right'))
            }
        }
    }
}

// 优化后:提前计算条件结果
build() {
    // 提前计算条件结果
    const showIcon = this.showIcon && this.item.icon;
    const showNote = this.item.note != null;
    const showRightText = this.showRightText && this.item.rightText;
    const showArrow = this.navigable && this.item.showArrow !== false;
    
    Row() {
        if (showIcon) {
            // 渲染图标
        }
        
        Column() {
            Text(this.item.title)
            
            if (showNote) {
                Text(this.item.note)
            }
        }
        
        Row() {
            if (showRightText) {
                Text(this.item.rightText)
            }
            
            if (showArrow) {
                Image($r('app.media.ic_arrow_right'))
            }
        }
    }
}

优化说明:

  1. 提前计算条件结果,减少重复计算
  2. 简化条件判断,提高代码可读性
  3. 减少条件判断的复杂度,提高渲染性能

3. 内存优化

3.1 资源复用
// 优化前:每次渲染都创建新的样式对象
build() {
    Row() {
        // 内容
    }
    .width('100%')
    .padding({ left: 16, right: 16, top: 12, bottom: 12 })
    .backgroundColor(this.item.disabled ? '#fafafa' : Color.White)
    .borderRadius(8)
}

// 优化后:复用样式对象
// 定义常量样式
private static readonly COMMON_STYLE = {
    width: '100%',
    borderRadius: 8,
    padding: { left: 16, right: 16, top: 12, bottom: 12 }
};

private static readonly NORMAL_BG = Color.White;
private static readonly DISABLED_BG = '#fafafa';

build() {
    Row() {
        // 内容
    }
    .width(UVListItem.COMMON_STYLE.width)
    .padding(UVListItem.COMMON_STYLE.padding)
    .backgroundColor(this.item.disabled ? UVListItem.DISABLED_BG : UVListItem.NORMAL_BG)
    .borderRadius(UVListItem.COMMON_STYLE.borderRadius)
}

优化说明:

  1. 使用静态常量定义样式,避免重复创建样式对象
  2. 复用样式对象,减少内存占用
  3. 提高样式一致性,便于维护
3.2 图片资源优化
// 优化前:直接使用图片资源
Image(this.item.icon)
    .width(24)
    .height(24)
    .objectFit(ImageFit.Contain)

// 优化后:根据需要加载不同尺寸的图片
private getOptimizedIcon(icon: string | Resource): string | Resource {
    if (typeof icon === 'string') {
        return icon;
    }
    
    // 根据当前设备分辨率选择合适的图片资源
    const devicePixelRatio = getDevicePixelRatio();
    if (devicePixelRatio <= 1) {
        return $r('app.media.icon_small');
    } else if (devicePixelRatio <= 2) {
        return $r('app.media.icon_medium');
    } else {
        return $r('app.media.icon_large');
    }
}

// 使用优化后的图片资源
Image(this.getOptimizedIcon(this.item.icon))
    .width(24)
    .height(24)
    .objectFit(ImageFit.Contain)

优化说明:

  1. 根据设备分辨率加载不同尺寸的图片资源
  2. 减少内存占用,提高渲染性能
  3. 优化图片显示效果

4. 交互优化

4.1 点击反馈优化
// 优化前:简单的点击处理
.onClick(() => {
    if (!this.item.disabled) {
        // 执行点击操作
        this.item.onClick?.();
    }
})

// 优化后:添加点击反馈效果
.onClick(() => {
    if (!this.item.disabled) {
        // 执行点击操作
        this.item.onClick?.();
    }
})
.stateStyles({
    pressed: {
        opacity: 0.7,
        backgroundColor: '#f0f0f0'
    },
    disabled: {
        opacity: 0.5,
        backgroundColor: '#fafafa'
    }
})

优化说明:

  1. 添加状态样式,提供按下和禁用状态的视觉反馈
  2. 使用opacity和backgroundColor变化提供明显的交互反馈
  3. 提高用户体验,增强交互感知
4.2 手势交互优化
// 优化前:仅支持点击操作
.onClick(() => {
    // 点击处理
})

// 优化后:支持多种手势交互
.gesture(
    GestureGroup(GestureMode.Exclusive,
        TapGesture()
            .onAction(() => {
                // 点击处理
                if (!this.item.disabled) {
                    this.item.onClick?.();
                }
            }),
        LongPressGesture()
            .onAction(() => {
                // 长按处理
                if (!this.item.disabled && this.item.onLongPress) {
                    this.item.onLongPress();
                }
            }),
        SwipeGesture()
            .onAction((event: SwipeGestureEvent) => {
                // 滑动处理
                if (!this.item.disabled && this.item.onSwipe) {
                    this.item.onSwipe(event);
                }
            })
    )
)

优化说明:

  1. 支持点击、长按、滑动等多种手势交互
  2. 使用GestureGroup组合多种手势,并设置为互斥模式
  3. 为不同手势提供不同的处理函数,增强交互丰富性
4.3 动画效果优化
// 优化前:无动画效果
@Component
struct UVListItem {
    // 组件属性
    
    build() {
        // 构建UI
    }
}

// 优化后:添加动画效果
@Component
struct UVListItem {
    // 组件属性
    @State private isPressed: boolean = false;
    @State private isAnimating: boolean = false;
    
    build() {
        Row() {
            // 列表项内容
        }
        .width('100%')
        .padding(16)
        .backgroundColor(this.isPressed ? '#f0f0f0' : Color.White)
        .borderRadius(8)
        .opacity(this.item.disabled ? 0.5 : 1)
        .animation({
            duration: 200,
            curve: Curve.EaseInOut,
            iterations: 1,
            playMode: PlayMode.Normal
        })
        .onTouch((event: TouchEvent) => {
            if (event.type === TouchType.Down) {
                this.isPressed = true;
            } else if (event.type === TouchType.Up || event.type === TouchType.Cancel) {
                this.isPressed = false;
            }
        })
        .onClick(() => {
            if (!this.item.disabled) {
                // 点击动画
                this.isAnimating = true;
                animateTo({
                    duration: 100,
                    onFinish: () => {
                        this.isAnimating = false;
                        // 执行点击操作
                        this.item.onClick?.();
                    }
                }, () => {
                    this.isPressed = true;
                })
                
                animateTo({
                    duration: 100,
                    delay: 100
                }, () => {
                    this.isPressed = false;
                })
            }
        })
    }
}

优化说明:

  1. 添加按下状态和动画状态管理
  2. 使用animation属性为样式变化添加过渡效果
  3. 使用animateTo实现点击时的动画序列
  4. 通过onTouch事件精确控制按下状态

5. 总结与最佳实践

在本篇文章中,我们详细介绍了UVList组件的高级特性与性能优化技巧。通过这些优化,可以显著提升UVList组件的性能和用户体验。
通过本系列文章的学习,相信你已经掌握了UVList组件的开发和优化技巧。在实际项目中,可以根据具体需求灵活运用这些技巧,打造出高性能、高体验的列表组件。
下一章节我们将主要讲解实际的应用场景,敬请期待!


http://www.kler.cn/a/579024.html

相关文章:

  • 通领科技冲刺北交所
  • 使用 Elastic-Agent 或 Beats 将 Journald 中的 syslog 和 auth 日志导入 Elastic Stack
  • 创新算法!BKA-Transformer-BiLSTM黑翅鸢优化算法多变量时间序列预测
  • (十七) Nginx解析:架构设计、负载均衡实战与常见面试问题
  • uniapp对接打印机和电子秤
  • Win7重装不翻车!ISO镜像安全下载渠道+BIOS设置避雷手册
  • 基于单片机的智慧农业大棚系统(论文+源码)
  • Android SharedPreferences 工具类封装:高效、简洁、易用
  • 操作系统控制台-健康守护我们的系统
  • ESP8266TCP客户端(单连接TCP Client)
  • 【JavaScript】08-作用域+箭头函数+解构赋值
  • 【vscode】一键编译运行c/c++程序
  • 基于opencv的hsv色块检测
  • Qt 进度条与多线程应用、基于 Qt 的文件复制工具开发
  • NO.32十六届蓝桥杯备战|函数|库函数|自定义函数|实参|形参|传参(C++)
  • 系统架构评估方法-ATAM方法
  • SQL根据分隔符折分不同的内容放到临时表
  • 【SpringBoot】深入剖析 Spring Boot 自动装配原理(附源码与实战)
  • vue3 vite项目安装eslint
  • python将目录下的所欲md文件转化为html和pdf