amunds
amunds

Reputation: 702

How to design a flutter timeline widget with fixed times and variable events

I'm making a vertical timeline in flutter but I've hit a roadblock on how to design the timeline and event system. The image below is what I have and how I want it to show. The yellow container is the event, events can be on either side and overlap other events. Currently it's three rows inside a column, with the sides expanded and middle fixed width. Each dot is its own widget with a datetime associated with it.

Now my issue is, how can I make it so that the events line up with the center numbers based on datetime? I'm currently using positioned on the event with top, but I have no way of getting the distance from the top of the center widgets.

Timeline with event

main build

child: Column(
  mainAxisSize: MainAxisSize.max,
  children: <Widget>[
    IntrinsicHeight(
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          _buildLeftCol(),
          _buildCenterCol(CustomTime().times),
          _buildRightCol(12)
        ],
      ),
    )
  ],
),

_buildLeftCol

Widget _buildLeftCol() {
  return Expanded(
    child: Container(
      child: Stack(
        children: <Widget>[
          _buildEventItem(DateTime.now()),
        ],
      )
    ),
  );
}

_buildEventItem

Widget _buildEventItem(DateTime time) {

  var index = CustomTime().getIndexOf(time);
  var position = 41.0 * index;

  return Positioned(
    left: 160,
    top: position,
    child: Container(
      width: 200,
      height: 200,
      color: Colors.yellow,
      child: Text("data")
    ),
  );
}
Widget _buildCenterCol(List<DateTime> list) {
  return Column(children: list.map((time) => timeItem(time)).toList());
}

Widget timeItem(DateTime time) {
  if(time.minute != 00) {
    return Padding(
      padding: const EdgeInsets.only(top:8.0, bottom: 8.0),
      child: ClipRRect(
        borderRadius: BorderRadius.circular(9.0),
        child: Container(
          height: 18,
          width: 18,
          color: Color(0xFF0288D1),
        ),
      ),
    );
  } else {
    return ClipRRect(
      borderRadius: BorderRadius.circular(32.0),
      child: Container(
        height: 64,
        width: 64,
        color: Color(0xFF00305A),
        child: Center(child: Text(DateFormat('HH').format(time), style: TextStyle(color: Colors.white, fontSize: 32.0),))
      )
    );
  }
}

Upvotes: 0

Views: 5678

Answers (1)

You can try the timeline_tile package released recently. Currently it does not provide dotted lines, but you can easily achieve what you desire with its tiles, for example:

TimelineTile(
  alignment: TimelineAlign.center,
  rightChild: Container(
    constraints: const BoxConstraints(
      minHeight: 120,
    ),
    color: Colors.lightGreenAccent,
  ),
  leftChild: Container(
    color: Colors.amberAccent,
  ),
);

If aligned center os manual you can have children on both sides.

Also, the beautiful_timelines repository contains some examples built with this package.

Upvotes: 1

Related Questions