百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

HarmonyOS实战:快递信息时间轴效果实现

zhezhongyun 2025-05-28 21:40 108 浏览

前言

快递信息时间轴在购物软件中是必不可少的功能,通过时间轴可以展示快递从发货到派送的每一个环节。本篇文章通过代码的形式详细讲解在鸿蒙日常开发中如何实现时间轴的效果。(篇尾附有完整源码)


实现效果

先看最终实现的效果,下面通过代码讲解怎么一步步实现时间轴。

需求分析

  1. 快递信息时间轴整体包括三个状态:开始状态,当前状态,未达状态。
  2. 不同状态对应标题颜色及图标不同。
  3. 字体颜色可根据状态的不同改变。
  4. 提示文字可以根据具体情况是否显示
  5. 时间轴上的虚线可以根据当前节点布局的高度动态改变。(重点)

根据具体需求,采用 List 组件实现时间轴,然后通过控制不同 item 的状态来实现效果。

技术实现

  1. 定义节点数据对象,这里使用不同数字代表当前节点的状态:1 表示开始,2 表示当前,3 表示即将到达。
export class OrderDetailBean{
   nodeStatus?: number //当前节点状态 
   nodeName?: string //节点名称
   nodeNote?: string //节点备注
   nodeTime?: string //节点时间 
}
  1. 构建节点集合。
  aboutToAppear(): void {
    let order1 = new OrderDetailBean()
    order1.nodeStatus = 1
    order1.nodeName = "唐僧已经从长安出发"
    order1.nodeTime = "1900-7-25  14:30:03"
    order1.nodeNote = ""

    let order2 = new OrderDetailBean()
    order2.nodeStatus = 1
    order2.nodeName = "唐僧到达五指山"
    order2.nodeNote = "温馨提示:此处有妖猴出没"
    let order3 = new OrderDetailBean()
    order3.nodeStatus = 1
    order3.nodeName = "孙悟空护送唐僧西天取经"
    order3.nodeNote = "请小白龙提前准备,下一站化身白龙马。"
    let order4 = new OrderDetailBean()
    order4.nodeStatus = 2
    order4.nodeName = "唐僧到达高老庄"
    order3.nodeNote = "孙悟空大战猪八戒"
    let order5 = new OrderDetailBean()
    order5.nodeStatus = 3
    order5.nodeName = "唐僧即将到达流沙河"
    order5.nodeNote = "收服卷帘大将沙悟净。"
    let order6 = new OrderDetailBean()
    order6.nodeStatus = 3
    order6.nodeName = "唐僧即将到达大雷音"
    order6.nodeNote = "取得真经,修成正果。"
    this.list.push(order1, order2, order3, order4, order5,order6)
  }
  1. 使用 List 组件实现时间轴,鸿蒙的 List 组件原生支持横向和纵向布局,可以根据实际需求进行调整。这里使用默认纵向布局。
List(){
        ForEach(this.list,(item: object, index: number) => {
          this.itemView(this.list[index], index)
        })
      }.width("100%")
        .height("100%")
  1. 接下来就是绘制 List 的 item,从最终的效果图来看,虚线部分只会在首尾之间显示,这里通过集合长度判断。最后一条虚线不显示,虚线可以通过设置布局边框的不同样式实现,这里使用的BorderStyle.Dashe。
 // 时间轴
        if (this.index < this.totalSize - 1) {
          Stack()
            .width(0)
            .borderStyle(BorderStyle.Dashed)
            .borderWidth(0.8)
            .height(this.minHeight)
            .borderColor($r('app.color.color_gray'))

        }
  1. 同时虚线部分应该有最小高度,然后通过当前 Item 的高度变化动态改变虚线的高度,鸿蒙布局组件提供了 onAreaChange 方法用来监听当前布局高度的变化,通过修改最新高度来实现虚线的动态变化。注意这个 minHeight 必须使用@state修饰。
 .onAreaChange((oldValue: Area, newValue: Area) => {
        this.minHeight = newValue.height as number
      })
  1. 最后使用 Row 布局将虚线布局和内容布局横向排列,就可以实现虚线跟随内容高度变化。

完整源码


@Component
  struct ItemLayout {
    @State bean: OrderDetailProgressBean = new OrderDetailProgressBean()
    index: number = 0
    totalSize: number = 0
    @State minHeight: number = 54

    build() {
      Row() {
        Column() {
          // 时间轴节点
          Image(this.getImage(this.bean.nodeStatus ?? 0))
            .width(16)
            .height(16)
            .borderRadius(8)

          // 时间轴
          if (this.index < this.totalSize - 1) {
            Stack()
              .width(0)
              .borderStyle(BorderStyle.Dashed)
              .borderWidth(0.8)
              .height(this.minHeight)
              .borderColor("#BABEC4")

          }
        }

        // 内容区域
        Column() {
          Text(this.bean.nodeName)
            .fontSize(14)
            .fontColor(this.getColor(this.bean.nodeStatus ?? 0))
            .fontWeight(FontWeight.Medium)


          Text(this.bean.nodeTime)
            .fontSize(12)
            .fontColor(Color.Gray)
            .margin({
              top: 4,
            })
          Text(this.bean.nodeNote)
            .fontSize(12)
            .fontColor(this.bean.nodeStatus == 1 ? Color.Gray : Color.Orange)
            .margin({
              top: 8,
            })

        }
        .margin({
          left: 8,
        })
          .alignItems(HorizontalAlign.Start)
          .width("84%")
          .margin({
            left: 8,
          })
          .onAreaChange((oldValue: Area, newValue: Area) => {
            this.minHeight = newValue.height as number
          })
      }
      .alignItems(VerticalAlign.Top)
        .width("100%")
    }

    getImage(state: number) {
      if (state == 1) {
        return $r("app.media.icon_complete")
      } else if (state == 2) {
        return $r("app.media.icon_selecte")
      } else {
        return $r("app.media.icon_unselecte")
      }
    }

    getColor(state: number) {
      if (state == 1) {
        return $r("app.color.color_gray")
      } else if (state == 2) {
        return $r("app.color.color_black")
      } else {
        return $r("app.color.color_gray_1")
      }
    }
  }


总结

本文的重点是知道虚线可以根据设置布局样式实现,然后就是如何实现虚线和布局动态高度变化同步,通过鸿蒙原生组件提供的方法可以实现。

相关推荐

Python入门学习记录之一:变量_python怎么用变量

写这个,主要是对自己学习python知识的一个总结,也是加深自己的印象。变量(英文:variable),也叫标识符。在python中,变量的命名规则有以下三点:>变量名只能包含字母、数字和下划线...

python变量命名规则——来自小白的总结

python是一个动态编译类编程语言,所以程序在运行前不需要如C语言的先行编译动作,因此也只有在程序运行过程中才能发现程序的问题。基于此,python的变量就有一定的命名规范。python作为当前热门...

Python入门学习教程:第 2 章 变量与数据类型

2.1什么是变量?在编程中,变量就像一个存放数据的容器,它可以存储各种信息,并且这些信息可以被读取和修改。想象一下,变量就如同我们生活中的盒子,你可以把东西放进去,也可以随时拿出来看看,甚至可以换成...

绘制学术论文中的“三线表”具体指导

在科研过程中,大家用到最多的可能就是“三线表”。“三线表”,一般主要由三条横线构成,当然在变量名栏里也可以拆分单元格,出现更多的线。更重要的是,“三线表”也是一种数据记录规范,以“三线表”形式记录的数...

Python基础语法知识--变量和数据类型

学习Python中的变量和数据类型至关重要,因为它们构成了Python编程的基石。以下是帮助您了解Python中的变量和数据类型的分步指南:1.变量:变量在Python中用于存储数据值。它们充...

一文搞懂 Python 中的所有标点符号

反引号`无任何作用。传说Python3中它被移除是因为和单引号字符'太相似。波浪号~(按位取反符号)~被称为取反或补码运算符。它放在我们想要取反的对象前面。如果放在一个整数n...

Python变量类型和运算符_python中变量的含义

别再被小名词坑哭了:Python新手常犯的那些隐蔽错误,我用同事的真实bug拆给你看我记得有一次和同事张姐一起追查一个看似随机崩溃的脚本,最后发现罪魁祸首竟然是她把变量命名成了list。说实话...

从零开始:深入剖析 Spring Boot3 中配置文件的加载顺序

在当今的互联网软件开发领域,SpringBoot无疑是最为热门和广泛应用的框架之一。它以其强大的功能、便捷的开发体验,极大地提升了开发效率,成为众多开发者构建Web应用程序的首选。而在Spr...

Python中下划线 ‘_’ 的用法,你知道几种

Python中下划线()是一个有特殊含义和用途的符号,它可以用来表示以下几种情况:1在解释器中,下划线(_)表示上一个表达式的值,可以用来进行快速计算或测试。例如:>>>2+...

解锁Shell编程:变量_shell $变量

引言:开启Shell编程大门Shell作为用户与Linux内核之间的桥梁,为我们提供了强大的命令行交互方式。它不仅能执行简单的文件操作、进程管理,还能通过编写脚本实现复杂的自动化任务。无论是...

一文学会Python的变量命名规则!_python的变量命名有哪些要求

目录1.变量的命名原则3.内置函数尽量不要做变量4.删除变量和垃圾回收机制5.结语1.变量的命名原则①由英文字母、_(下划线)、或中文开头②变量名称只能由英文字母、数字、下画线或中文字所组成。③英文字...

更可靠的Rust-语法篇-区分语句/表达式,略览if/loop/while/for

src/main.rs://函数定义fnadd(a:i32,b:i32)->i32{a+b//末尾表达式}fnmain(){leta:i3...

C++第五课:变量的命名规则_c++中变量的命名规则

变量的命名不是想怎么起就怎么起的,而是有一套固定的规则的。具体规则:1.名字要合法:变量名必须是由字母、数字或下划线组成。例如:a,a1,a_1。2.开头不能是数字。例如:可以a1,但不能起1a。3....

Rust编程-核心篇-不安全编程_rust安全性

Unsafe的必要性Rust的所有权系统和类型系统为我们提供了强大的安全保障,但在某些情况下,我们需要突破这些限制来:与C代码交互实现底层系统编程优化性能关键代码实现某些编译器无法验证的安全操作Rus...

探秘 Python 内存管理:背后的神奇机制

在编程的世界里,内存管理就如同幕后的精密操控者,确保程序的高效运行。Python作为一种广泛使用的编程语言,其内存管理机制既巧妙又复杂,为开发者们提供了便利的同时,也展现了强大的底层控制能力。一、P...