Flutter通过Container实现时间轴效果

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

时间轴的特点
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) :

二、重写 BorderDirectional 中 paint 方法

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

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());
    }
  }

最终效果

三、完整代码

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

以上就是Flutter通过Container实现时间轴效果的详细内容,更多关于Flutter 实现时间轴效果的资料请关注我们其它相关文章!

(0)

相关推荐

  • flutter Container容器实现圆角边框

    本文实例为大家分享了flutter Container容器实现圆角边框的具体代码,供大家参考,具体内容如下 在这里使用 Container 容器来实现圆角矩形边框效果 1 圆角矩形边框 Container( margin: EdgeInsets.only(left: 40, top: 40), //设置 child 居中 alignment: Alignment(0, 0), height: 50, width: 300, //边框设置 decoration: new BoxDecoration

  • Flutter时间轴Timeline的实现

    首先看看时间轴效果图 实现的难点就是左边的时间线,右边的事件说白了就是一个ListView,仔细观察一下会发现圆圈在ListView的一个item上,想明白这些我们就可以把圆圈和右边的事件作为一个listitem实现,左边的竖线可以有两种实现方法 1)listItem是一个Row,Row里含有一条竖线 2)Stack实现,Stack有两个child widget,一个是竖线,一个是ListView 本文简单用第二种来实现它,废话少说先上代码 @override Widget build(Buil

  • Flutter通过Container实现时间轴效果

    时间轴是前端UI经常用到的效果,先看下效果图: 时间轴的特点 1.在列表中的高度不确定,高度取决于右侧 item 的高度 2.时间轴通常在第一个 item 中的样式和其他 item 中不同. 实现 一.借助 Container 中 decoration 属性,设置左侧的 border,可以实现时间轴高度随着 item 变化效果 Center( child: Container( width: 100, height: 100, decoration: BoxDecoration( // 设置 B

  • Android控件之使用ListView实现时间轴效果

     实现思路: 该View是通过ListView实现的,通过实体两个字段内容content和时间time来展示每个ListItem 时间轴是使用上面一条线(20dp)和中间一个圆(15dp)和下面一条线(40dp)组装成的 在ListView中,设置其分割线为空,并且没有点击效果 效果图: 步骤一:使用xml画出一个灰色的圆点(time_cycle.xml) <?xml version="1.0" encoding="utf-8"?> <shape

  • Android自定义指示器时间轴效果实例代码详解

    指示器时间轴在外卖.购物类的APP里会经常用到,效果大概就像下面这样,看了网上很多文章,大都是自己绘制,太麻烦,其实通过ListView就可以实现. 在Activity关联的布局文件activity_main.xml中放置一个ListView,代码如下.由于这个列表只是用于展示信息,并不需要用户去点击,所以将其clickable属性置为false:为了消除ListView点击产生的波纹效果,我们设置其listSelector属性的值为透明:我们不需要列表项之间的分割线,所以设置其divider属

  • Android实现快递物流时间轴效果

    本文实例为大家分享了Android实现快递物流时间轴效果展示的具体代码,供大家参考,具体内容如下 首先,这篇参考了别人的代码.根据自己的项目需求简单改造了一下,效果图如下 xml:代码 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:lay

  • Android使用自定义View实现横行时间轴效果

    前言 本篇文章会说下如何使用并且要用麻烦的自定义 view 去实现时间轴效果,以及如何分析.实现自定义 view. 需要具备的知识:Paint.Canvas.自定义 view 的绘制流程. 欢迎留言交流. 一.已经有很多 RecycleView 实现时间轴的例子,为何还要费劲的使用自定义 view 去实现时间轴? 首先看下最终想要的效果: 根据上图可以总结出以下几点: 每个阶段要显示时间.阶段名.状态图标.中间有虚线: 文字上下交错显示: 相邻阶段的文字在垂直方向上是可以相交的: 时间轴的个数不

  • vue+swiper实现时间轴效果

    本文实例为大家分享了vue+swiper实现时间轴效果的具体代码,供大家参考,具体内容如下 效果: 首先引入,有淘宝镜像的用 cnpm install swiper --save 没有的用 npm install swiper --save <template> <div class="hello" style="height:100%;width:100%;position:relative;"> <div class="s

  • vue实现物流时间轴效果

    本文实例为大家分享了vue实现物流时间轴效果的具体代码,供大家参考,具体内容如下 son组件(物流时间轴组件) <template> <div class="steps-wrap"> <ul> <li v-for="(item,index) in steps" :key="index"> <span class="time">{{item.time}}</spa

  • Vue实现时间轴效果

    本文实例为大家分享了Vue实现时间轴效果的具体代码,供大家参考,具体内容如下 时间轴上的时间点数和描述文本均可自定义设置 效果图如下: ①创建时间轴组件Timeline.vue: <template>   <div class="m-timeline-area">     <div class="m-timeline">       <div         :class="['m-timeline-item',

  • angularjs实现时间轴效果的示例代码

    一 引入包 引入angular-timeline包. 下载地址:angular-timeline.zip 在index.html中引入 <link href="lib/angular-timeline/dist/angular-timeline.css" rel="external nofollow" rel="stylesheet"> <script src="lib/angular-timeline/dist/an

  • jQuery Timelinr实现垂直水平时间轴插件(附源码下载)

    jquery.timelinr.js是一款效果非常炫酷的jQuery时间轴插件.jquery.timelinr可以制作水平和垂直时间轴效果,并且可以进行自动播放.你可以通过参数来控制每次时间轴切换的动画效果. 推荐阅读:之前分享过一款 jQuery实现企业发展简史时间轴特效源码 ,它的界面展示效果很不错. 效果展示       源码下载 使用方法 使用该时间轴插件需要在页面中引入jQuery和jquery.timelinr.js文件. <script src="js/jquery-1.x.

随机推荐