Flutter - not enough space to scroll to index in listview

Viewed 54

I am working with a package called sticky_grouped_list (https://pub.dev/packages/sticky_grouped_list) that also has all the functionality of scrollable_positioned_list package (https://pub.dev/packages/scrollable_positioned_list).

I am trying to scroll to index according to selected day in calendar, I have implemented all the logic but when I select a day it try to scroll to index but then it goes back to the top

you can see here what I am talking about:

enter image description here

this is what I am looking for (notice that there is enough space at the bottom to scroll):

enter image description here

this is what I have so far:

class PlanificationPage extends StatefulWidget {
  const PlanificationPage({Key? key}) : super(key: key);

  @override
  State<PlanificationPage> createState() => _PlanificationPageState();
}

class _PlanificationPageState extends State<PlanificationPage> {
  final RefreshController refreshListController =
      RefreshController(initialRefresh: false);
  final GroupedItemScrollController itemScrollController =
      GroupedItemScrollController();
  final ItemPositionsListener itemPositionsListener =
      ItemPositionsListener.create();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  moveToIndex(index) {
    if (itemScrollController.isAttached) {
      itemScrollController.scrollTo(
          index: index, duration: const Duration(milliseconds: 500));
    }
  }

  @override
  Widget build(BuildContext context) {
    final adminBloc = BlocProvider.of<AdminBloc>(context);
    return Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: Text(
            AppStrings.whiteboardProgrammingTitle,
            style: UiHelper.appBartextStyle,
          ),
        ),
        body: Column(
          children: [
            Container(
              padding: const EdgeInsets.only(top: 10),
              color: Theme.of(context).colorScheme.surface,
              child: BlocBuilder<AdminBloc, AdminState>(
                builder: (context, state) {
                  return TableCalendar(
                    firstDay: DateTime.utc(2010, 10, 16),
                    lastDay: DateTime.utc(2030, 3, 14),
                    focusedDay: state.focusedDay!,
                    calendarFormat: CalendarFormat.week,
                    startingDayOfWeek: StartingDayOfWeek.monday,
                    headerVisible: false,
                    selectedDayPredicate: (DateTime day) {
                      return isSameDay(state.selectedDay, day);
                    },
                    onDaySelected: (DateTime selectedDay, DateTime focusedDay) {
                      if (!isSameDay(state.selectedDay, selectedDay)) {
                        adminBloc.add(OnSelectedDay(
                          selectedDay: selectedDay,
                          focusedDay: focusedDay,
                        ));

                        moveToIndex(selectedDay.weekday - 1);
                      }
                    },
                    onPageChanged: (DateTime focusedDay) {
                      adminBloc
                        ..add(OnPageCalendarChangedEvent(focusedDay))
                        ..add(OnLoadWorkoutsEvent());
                    },
                    onCalendarCreated: (_) {
                      adminBloc.add(OnLoadWorkoutsEvent());
                    },
                  );
                },
              ),
            ),
            BlocBuilder<AdminBloc, AdminState>(
              builder: (context, state) {
                if (state.loadingList) {
                  return const Center(
                    child: CircularProgressIndicator(),
                  );
                }
                final List<WorkoutsByDatesModel> workouts = state.listWorkouts;
                return Expanded(
                  child: SmartRefresher(
                    controller: refreshListController,
                    enablePullDown: true,
                    onRefresh: () {
                      BlocProvider.of<AdminBloc>(context)
                          .add(OnLoadWorkoutsEvent());
                      refreshListController.refreshCompleted();
                    },
                    child: SingleChildScrollView(
                      child:
                          StickyGroupedListView<WorkoutsByDatesModel, String>(
                        shrinkWrap: true,
                        elements: workouts,
                        //padding: const EdgeInsets.only(bottom: 500.0), // ==> I tried add padding and I have the same behaivour
                        //physics: const AlwaysScrollableScrollPhysics(),
                        itemScrollController: itemScrollController,
                        groupBy: (WorkoutsByDatesModel element) =>
                            element.date.weekday.toString(),
                        groupComparator: (value1, value2) =>
                            value1.compareTo(value2),
                        groupSeparatorBuilder: (WorkoutsByDatesModel value) =>
                            Padding(
                          padding: const EdgeInsets.only(top: 10.0, bottom: 10),
                          child: Center(
                            child: Text(
                              AppUtils.getDayName(value.date.weekday),
                              style: const TextStyle(
                                fontSize: 12,
                              ),
                            ),
                          ),
                        ),
                        indexedItemBuilder: (BuildContext context,
                            WorkoutsByDatesModel element, int index) {
                          final workouts = element.workouts;
                          return ListView.builder(
                            shrinkWrap: true,
                            physics: const NeverScrollableScrollPhysics(),
                            itemCount: workouts.length + 1,
                            itemBuilder: (BuildContext context, int i) {
                              if (i == workouts.length) {
                                return GestureDetector(
                                  onTap: () {
                                    context
                                        .read<AdminBloc>()
                                        .add(OnSelectedCardDay(element.date));
                                    context.router.push(
                                        const WorkoutTypeSelectionRouter());
                                  },
                                  child: Container(
                                    color:
                                        Theme.of(context).colorScheme.surface,
                                    padding: const EdgeInsets.symmetric(
                                        horizontal: 20, vertical: 10),
                                    child: Row(
                                      children: [
                                        const Icon(
                                          Icons.add_circle_rounded,
                                          size: 16,
                                        ),
                                        const SizedBox(width: 5),
                                        Text(
                                          AppStrings.addNewWorkout,
                                          style: const TextStyle(fontSize: 16),
                                        )
                                      ],
                                    ),
                                  ),
                                );
                              } else {
                                return Slidable(
                                  endActionPane: ActionPane(
                                    motion: const ScrollMotion(),
                                    children: [
                                      SlidableAction(
                                        onPressed: (context) {
                                          //TODO: NAVIGATE TO EDIT WORKOUT PAGE
                                          print('edit');
                                        },
                                        backgroundColor: Colors.blue,
                                        foregroundColor: Colors.white,
                                        label: AppStrings.editButton,
                                      )
                                    ],
                                  ),
                                  child: Container(
                                    color:
                                        Theme.of(context).colorScheme.surface,
                                    padding: const EdgeInsets.symmetric(
                                        horizontal: 20),
                                    child: Column(
                                      crossAxisAlignment:
                                          CrossAxisAlignment.start,
                                      children: [
                                        Padding(
                                          padding: const EdgeInsets.all(4.0),
                                          child: Text(
                                              AppStrings.workoutOfDayTitle,
                                              style: TextStyle(
                                                  fontSize: 10,
                                                  color: Theme.of(context)
                                                      .disabledColor)),
                                        ),
                                        Padding(
                                          padding: const EdgeInsets.only(
                                              left: 8.0, bottom: 10),
                                          child: Text(
                                            workouts[i].title,
                                            style: const TextStyle(
                                              fontWeight: FontWeight.w500,
                                              fontSize: 16,
                                            ),
                                          ),
                                        ),
                                        Container(
                                          height: 0.5,
                                          width: double.infinity,
                                          color: Theme.of(context).dividerColor,
                                        ),
                                      ],
                                    ),
                                  ),
                                );
                              }
                            },
                          );
                        },
                      ),
                    ),
                  ),
                );
              },
            ),
          ],
        ));
  }
}

how can I have enough space at the bottom to scroll to index without this behavior or what I am doing wrong? please any help is appreciated

0 Answers
Related