Flutter 时间线

需求

电商网站常会用到的物流时间线
在这里插入图片描述

方法一

利用Stack做,一层渲染,一层渲染列表和表示状态的圆点
注意点1:因为Stack的高度约束是0~infinity,默认子Container高度为0,设置top、bottom后才能显示
注意点2:text需要包裹Expanded,否则无法换行
注意点3:最外层要包裹Column,Stack高度会随子集变化而变化,否则高度会占满整个屏幕

import 'package:flutter/material.dart';

class DateLine extends StatelessWidget {

  final List textList = [
    '[收货地址]浙江省宁波市鄞州区 中河街道 甬兴西路甬兴新村 185****4512',
    '您的快件已暂存至宁波市甬兴新村菜鸟驿站,您的快件已暂存至宁波市甬兴新村菜鸟驿站,请及时取件有问题请联系请及时取件有问题请联系',
    '[宁波市]宁波市鄞州区的李XXXXXX[]正在派件',
    '[宁波市]快件已到达宁波鄞州区',
    '[宁波市]快件已到达宁波鄞州区',
    '商品已下单',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('时间线'),),
      body: Column(children: [
        Padding(padding: EdgeInsets.all(15),
            child: Stack(children: [
              //线
              Positioned(left: 10,top: 10,bottom: 0,//重点,因为Stack的高度约束是0~infinity,默认子Container高度为0,设置top、bottom后才能显示
                child: Container(width: 1,color: Colors.red,),),
              //列表
              Column(crossAxisAlignment: CrossAxisAlignment.start,children: List.generate(6, (index){
                return Container(padding: EdgeInsets.only(bottom: 20),child: Column(children: [
                  Row(crossAxisAlignment: CrossAxisAlignment.start,children: [
                    //状态圆点
                    Container(width: 20,height: 20,alignment: Alignment.center,
                      child: Container(width: 12,height: 12,decoration: BoxDecoration(borderRadius: BorderRadius.circular(6),color: Colors.yellow),),),
                    SizedBox(width: 5,),
                    //文字信息
                    Expanded(child: Text(this.textList[index],style: TextStyle(color: Colors.grey,fontSize: 14),)),
                  ],),
                  SizedBox(height: 5,),
                  Row(children: [
                    SizedBox(width: 25,),
                    Text('2021-12-28 13:56:25',style: TextStyle(color: Colors.grey,fontSize: 12),)
                  ],)
                ],),);
              }),)
            ],)
        ),
      ],),
    );
  }
}

效果
在这里插入图片描述
待解决问题
最后一个子集有线条露出

方法一改

解决最后一个子集有线条露出问题。
为最后一个子集创建Stack,遮盖线条

import 'package:flutter/material.dart';

class DateLine extends StatelessWidget {

  final List textList = [
    '[收货地址]浙江省宁波市鄞州区 中河街道 甬兴西路甬兴新村 185****4512',
    '您的快件已暂存至宁波市甬兴新村菜鸟驿站,您的快件已暂存至宁波市甬兴新村菜鸟驿站,请及时取件有问题请联系请及时取件有问题请联系',
    '[宁波市]宁波市鄞州区的李XXXXXX[]正在派件',
    '[宁波市]快件已到达宁波鄞州区',
    '[宁波市]快件已到达宁波鄞州区',
    '商品已下单',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('时间线'),),
      body: Container(color: Colors.white,
        child: Column(children: [
          Padding(padding: EdgeInsets.all(15),
              child: Stack(children: [
                //线
                Positioned(left: 10,top: 10,bottom: 0,//重点,因为Stack的高度约束是0~infinity,默认子Container高度为0,设置top、bottom后才能显示
                  child: Container(width: 1,color: Colors.red,),),
                //列表
                Column(crossAxisAlignment: CrossAxisAlignment.start,children: List.generate(this.textList.length, (index){
                  if(index == this.textList.length - 1){
                    //最后一个节点
                    return Stack(children: [
                      Container(padding: EdgeInsets.only(bottom: 20),child: Column(children: [
                        Row(crossAxisAlignment: CrossAxisAlignment.start,children: [
                          //状态圆点
                          Container(width: 20,height: 20,alignment: Alignment.center,
                            child: Container(width: 8,height: 8,decoration: BoxDecoration(borderRadius: BorderRadius.circular(6),color: Colors.yellow),),),
                          SizedBox(width: 5,),
                          //文字信息
                          Expanded(child: Text(this.textList[index],style: TextStyle(color: Colors.grey,fontSize: 14),)),
                        ],),
                        SizedBox(height: 5,),
                        Row(children: [
                          SizedBox(width: 25,),
                          Text('2021-12-28 13:56:25',style: TextStyle(color: Colors.grey,fontSize: 12),)
                        ],)
                      ],),),
                      Positioned(top: 14,bottom: 0,child: Container(width: 20,color: Colors.white,))
                    ],);
                  }else{
                    return Container(padding: EdgeInsets.only(bottom: 20),child: Column(children: [
                      Row(crossAxisAlignment: CrossAxisAlignment.start,children: [
                        //状态圆点
                        Container(width: 20,height: 20,alignment: Alignment.center,
                          child: Container(width: 8,height: 8,decoration: BoxDecoration(borderRadius: BorderRadius.circular(6),color: Colors.yellow),),),
                        SizedBox(width: 5,),
                        //文字信息
                        Expanded(child: Text(this.textList[index],style: TextStyle(color: Colors.grey,fontSize: 14),)),
                      ],),
                      SizedBox(height: 5,),
                      Row(children: [
                        SizedBox(width: 25,),
                        Text('2021-12-28 13:56:25',style: TextStyle(color: Colors.grey,fontSize: 12),)
                      ],)
                    ],),);
                  }

                }),)
              ],)
          ),
        ],),
      ),
    );
  }

}

最终效果
在这里插入图片描述

方法二

利用边框做线,Stack绘制状态圆点

import 'package:flutter/material.dart';

class DateLine extends StatelessWidget {

  final List textList = [
    '[收货地址]浙江省宁波市鄞州区 中河街道 甬兴西路甬兴新村 185****4512',
    '您的快件已暂存至宁波市甬兴新村菜鸟驿站,您的快件已暂存至宁波市甬兴新村菜鸟驿站,请及时取件有问题请联系请及时取件有问题请联系',
    '[宁波市]宁波市鄞州区的李XXXXXX[]正在派件',
    '[宁波市]快件已到达宁波鄞州区',
    '[宁波市]快件已到达宁波鄞州区',
    '商品已下单',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('时间线'),),
      body: Container(color: Colors.white,
        child: Column(children: List.generate(this.textList.length, (index){
          return Container(width: double.infinity,child: Stack(children: [
            Container(padding: EdgeInsets.only(left: 20,bottom: 25),margin: EdgeInsets.only(left: 20),
              //绘制边框线,最后一个不绘制
              decoration: BoxDecoration(border: Border(left: BorderSide(color: index == this.textList.length - 1 ? Colors.white : Colors.blue,width: 1))),
              child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [
                Text(this.textList[index],style: TextStyle(color: Colors.grey,fontSize: 12),),
                SizedBox(width: 25,),
                Text('2021-12-28 13:56:25',style: TextStyle(color: Colors.grey,fontSize: 10),)
              ],),
            ),
            //状态圆点
            Positioned(left: 12.5,top: 0,
              child: Container(width: 15,height: 15,decoration:   BoxDecoration(borderRadius: BorderRadius.circular(20),color: Colors.yellow),),
            ),
          ],),);
        }),),
      )
    );
  }

}

效果
在这里插入图片描述

待解决问题
当圆点直径和文字的高度一致时,效果最好
当圆点直径小于文字的高度,如果不给圆点加top,与文字垂直上无法对其,如果加上top,第一个圆点上线条会冒尖,最后一个圆点上会有一部分空缺
当圆点直径大于文字的高度,与文字无法对其
请大佬赐教。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值