Toby
Toby

Reputation: 13

Flutter Widget offset in a ListView does not perform like expected

I made a timetable schedule with items inside.

Each slot (60min) does have a fixed size (200).
So an event with 60min duration does have a height of 200.
An Event with 30min does have an height of 100. The offset and height does work like expected when an event starts XX:15 / XX:30 / XX:45.

But when I scroll the ScrollView the item disappears, as soon as the slot leaves the view.

enter image description here

I tried a CustomScrollView with a SliverList making for each Timeslot a TimeslotRow.

This is the ScrollView:

Expanded(
    child: CustomScrollView(   
       slivers: [
          SliverList(
             delegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) {
                 return TimeslotRow(
                   timeslot_items[index].name,
                   timeslot_items[index].items,
                 );
              },
              childCount: timeslot_items.length,
           ),
          )
        ],
     ),
 )

This is the TimeslotRow as a SizedOverflowBox:

 Widget TimeslotRow(
    String slot,
    List<TerminItem> items,
  ) {
    return SizedOverflowBox(
      alignment: Alignment.topLeft,
      size: const Size(double.infinity, 200),
      child: Container(
        decoration: const BoxDecoration(
          border: Border(
            top: BorderSide(width: 1.5, color: backgroundColor),
          ),
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            if (Responsive.isDesktop(context))
              Expanded(
                  flex: 1,
                  child: SizedBox(
                    child: Text(slot),
                  )),
            Expanded(
                flex: 3,
                child: items
                        .where((item) => item.saal == 0)
                        .toList()
                        .map((item) => TerminWidget(item))
                        .toList()
                        .isNotEmpty
                    ? Stack(
                        children: items
                            .where((item) => item.saal == 0)
                            .toList()
                            .map((item) => TerminWidget(item))
                            .toList(),
                      )
                    : EmptyTimeslotItem(slot, 0)),
            Expanded(
                flex: 3,
                child: items
                        .where((item) => item.saal == 1)
                        .toList()
                        .map((item) => TerminWidget(item))
                        .toList()
                        .isNotEmpty
                    ? Stack(
                        children: items
                            .where((item) => item.saal == 1)
                            .toList()
                            .map((item) => TerminWidget(item))
                            .toList(),
                      )
                    : EmptyTimeslotItem(slot, 1)),
            Expanded(
                flex: 3,
                child: items
                        .where((item) => item.saal == 2)
                        .toList()
                        .map((item) => TerminWidget(item))
                        .toList()
                        .isNotEmpty
                    ? Stack(
                        children: items
                            .where((item) => item.saal == 2)
                            .toList()
                            .map((item) => TerminWidget(item))
                            .toList(),
                      )
                    : EmptyTimeslotItem(slot, 2)),
          ],
        ),
      ),
    );
  }

Each TimeslotRow does have events starting at this timeslot-time. In the TerminWidget the Offset is calculated and the height:

Widget TerminWidget(TerminItem item) {
    return Transform.translate(
      offset: Offset(
          0,
          item.start.minute == 15
              ? 50
              : item.start.minute == 30
                  ? 100
                  : item.start.minute == 45
                      ? 150
                      : 0),
      child: InkWell(
        onTap: () {
          if (item.name == "Privatstunde") {
            PrivateTermin termin = PrivateTermin(
                name: item.note1,
                kontakt: item.note2,
                song: item.note3,
                selection: item.name,
                time: Timestamp.fromDate(item.start),
                dauer: item.dauer,
                saal: item.saal == 0
                    ? "Saal Blau"
                    : item.saal == 1
                        ? "Saal Lila"
                        : "Saal Grün",
                teacher: item.teacher,
                privateRef: item.privateRef,
                uid: item.uid);
            showPrivateDialog_Info(termin);
          }
        },
        child: Container(
          padding: const EdgeInsets.all(10),
          margin: const EdgeInsets.only(right: 20, top: 2, left: 2),
          width: double.infinity,
          height: item.dauer * 3.333333333,
          decoration: BoxDecoration(
              borderRadius: const BorderRadius.only(
                  topRight: Radius.circular(10),
                  bottomRight: Radius.circular(10)),
              border: Border(
                left: BorderSide(width: 6, color: saalIndicators[item.saal]),
                top: BorderSide(width: 1, color: saalIndicators[item.saal]),
                right: BorderSide(width: 1, color: saalIndicators[item.saal]),
                bottom: BorderSide(width: 1, color: saalIndicators[item.saal]),
              ),
              color: saalBackgrounds[item.saal]),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.max,
            children: [
              Text(
                  "${DateFormat('HH:mm').format(item.start)} Uhr - ${DateFormat('HH:mm').format(item.start.add(Duration(minutes: item.dauer)))} Uhr"),
              Text(
                item.name,
                style:
                    const TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
              ),
              Text(item.note1),
              Text(item.teacher)
            ],
          ),
        ),
      ),
    );
  }

Upvotes: 0

Views: 35

Answers (0)

Related Questions