Flutter通过Container实现时间轴效果

作者:码农王真实 时间:2023-10-04 09:40:45 

目录
  • 时间轴是前端UI经常用到的效果,先看下效果图:

  • 实现

    • 一、借助 Container 中 decoration 属性,设置左侧的 border,可以实现时间轴高度随着 item 变化效果

    • 二、重写 BorderDirectional 中 paint 方法

    • 三、完整代码

时间轴是前端UI经常用到的效果,先看下效果图:

Flutter通过Container实现时间轴效果

时间轴的特点
1、在列表中的高度不确定,高度取决于右侧 item 的高度
2、时间轴通常在第一个 item 中的样式和其他 item 中不同。

实现

一、借助 Container 中 decoration 属性,设置左侧的 border,可以实现时间轴高度随着 item 变化效果


     Center(
         child: Container(
       width: 100,
       height: 100,
       decoration: BoxDecoration(
       // 设置 BoxDecoration 的 border, border  的高度就是 Container 的高度
         border: Border(left: BorderSide(color: Colors.red)),
         color: Color(0x11000000),
       ),
     ))

效果 (图中红线是 Container 左侧的 border,可以在这里扩展成 timeline) :

Flutter通过Container实现时间轴效果

二、重写 BorderDirectional 中 paint 方法

BorderDirectional 中原来的 paint 方法,可以看出,设置不同的属性,会调用不同的绘制方法实现不同的效果,这里重新 paint 方法,实现时间轴的效果

Flutter通过Container实现时间轴效果

paint 方法中参数
canvas : 这个就是画布了,借助这个 canvas 可以随意实现各种效果
rect : Container 的范围大小

我们的 paint 方法实现,按照 UI 设计图,对应的位置画上圆和线就可以了


 @override
 void paint(Canvas canvas, Rect rect, {TextDirection? textDirection, BoxShape shape = BoxShape.rectangle, BorderRadius? borderRadius}) {
   if (position != 1) {
     canvas.drawLine(Offset(rect.left+margin + radius / 2, rect.top), Offset(rect.left +margin+ radius / 2, rect.bottom), _strokePaint());
     canvas.drawCircle(Offset(rect.left +margin+ radius / 2, rect.top + radius * 2), radius, _fillPaint());
     canvas.drawCircle(Offset(rect.left +margin+ radius / 2, rect.top + radius * 2), radius,_strokePaint());
   } else {
     canvas.drawLine(Offset(rect.left+margin + radius / 2, rect.top + radius * 2), Offset(rect.left+margin + radius / 2, rect.bottom), _strokePaint());
     canvas.drawCircle(Offset(rect.left+margin + radius / 2, rect.top + radius * 2), radius, _fillPaint());
     canvas.drawCircle(Offset(rect.left +margin+ radius / 2, rect.top + radius * 2), radius, _strokePaint());
     canvas.drawCircle(Offset(rect.left +margin+ radius / 2, rect.top + radius * 2), radius / 2, _strokePaint());
   }
 }

最终效果

Flutter通过Container实现时间轴效果

三、完整代码


class BorderTimeLine extends BorderDirectional {
 int position;

BorderTimeLine(this.position);

double radius = 10;
 double margin= 20;
 Paint _paint = Paint()
   ..color = Color(0xFFDDDDDD)
   ..strokeWidth = 1;

@override
 void paint(Canvas canvas, Rect rect, {TextDirection? textDirection, BoxShape shape = BoxShape.rectangle, BorderRadius? borderRadius}) {
   if (position != 0) {
     canvas.drawLine(Offset(rect.left+margin + radius / 2, rect.top), Offset(rect.left +margin+ radius / 2, rect.bottom), _strokePaint());
     canvas.drawCircle(Offset(rect.left +margin+ radius / 2, rect.top + radius * 2), radius, _fillPaint());
     canvas.drawCircle(Offset(rect.left +margin+ radius / 2, rect.top + radius * 2), radius,_strokePaint());
   } else {
     canvas.drawLine(Offset(rect.left+margin + radius / 2, rect.top + radius * 2), Offset(rect.left+margin + radius / 2, rect.bottom), _strokePaint());
     canvas.drawCircle(Offset(rect.left+margin + radius / 2, rect.top + radius * 2), radius, _fillPaint());
     canvas.drawCircle(Offset(rect.left +margin+ radius / 2, rect.top + radius * 2), radius, _strokePaint());
     canvas.drawCircle(Offset(rect.left +margin+ radius / 2, rect.top + radius * 2), radius / 2, _strokePaint());
   }
 }

Paint _fillPaint(){
   _paint.color=Colors.white;
   _paint.style=PaintingStyle.fill;
   return _paint;
 }
 Paint _strokePaint(){
   _paint.color=Color(0xFFDDDDDD);
   _paint.style=PaintingStyle.stroke;
   return _paint;
 }
}

在 ListView 中的 item 中使用


 Widget _buildItem(BuildContext c, int i) {
   return Container(
       width: double.infinity,
       padding: EdgeInsets.symmetric(horizontal: 20),
       decoration: BoxDecoration(border: BorderTimeLine(i)),
       child: Padding(
         padding: const EdgeInsets.symmetric(horizontal: 20),
         child: Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [
           Padding(padding: EdgeInsets.symmetric(vertical: 10)),
           Divider(color: Colors.grey.shade300, thickness: 40),
           Text("$i" * 6, style: TextStyle(color: Colors.black, fontSize: 16)),
           Text("abc\n" * Random().nextInt(10)),
           Padding(padding: EdgeInsets.symmetric(vertical: 10)),
         ]),
       ));
 }

全部代码 github

来源:https://juejin.cn/post/6963476792669634590

标签:Flutter,Container,时间轴
0
投稿

猜你喜欢

  • mybatis foreach 循环 list(map)实例

    2023-11-23 23:39:05
  • 浅谈Android ASM自动埋点方案实践

    2021-10-19 22:01:18
  • C#面向对象编程中开闭原则的示例详解

    2022-12-07 11:15:28
  • Android集成Flutter

    2023-07-06 13:07:33
  • java构造函数示例(构造方法)

    2022-05-08 19:06:03
  • 在springboot中实现个别bean懒加载的操作

    2023-11-25 09:44:11
  • MybatisPlus中@TableField注解的使用详解

    2021-11-01 23:05:35
  • 解决springboot URL带有斜杠的转义字符百分之2F导致的400错误

    2022-05-08 07:27:32
  • 深入解析java中的locale

    2023-11-09 18:14:20
  • 浅析Spring和MyBatis整合及逆向工程

    2022-07-09 08:27:11
  • C#集合之字典的用法

    2022-04-11 23:27:19
  • C# 的析构以及垃圾回收实例分析

    2021-12-22 19:03:37
  • c#和avascript加解密之间的互转代码分享

    2022-03-22 10:15:28
  • C#有效防止同一账号多次登录(附三种方法)

    2023-05-23 10:32:45
  • springboot 在idea中实现热部署的方法

    2022-10-24 22:27:19
  • hutool实战:IoUtil 流操作工具类(将内容写到流中)

    2022-11-16 09:17:47
  • JAVA实现经典扫雷游戏的示例代码

    2022-01-26 04:20:18
  • java解析json数组方式

    2023-08-10 17:22:14
  • Monaco Editor实现sql和java代码提示实现示例

    2023-01-31 16:59:48
  • Android指纹识别API初试

    2023-01-15 20:16:11
  • asp之家 软件编程 m.aspxhome.com