fix: replace Column+Expanded with CustomScrollView on calendar screen

The mobile calendar layout had a split-height bug where the event list
at the bottom was squeezed into whatever pixel crumbs remained after the
calendar card and summary bar consumed their fixed space. On small phones
or 6-row months (~390px calendar), the events area could shrink to under
100px — barely one card, with no way to scroll.

Fix: replace Column + Expanded(ListView) with a CustomScrollView using
slivers so the full page — calendar card, summary bar, and event cards —
scrolls as one unified surface. SliverFillRemaining handles loading and
empty states so they always fill the visible viewport naturally.
This commit is contained in:
2026-03-18 16:39:48 +05:30
parent 8d9bbe888e
commit 2c109f692c

View File

@@ -637,32 +637,54 @@ class _CalendarScreenState extends State<CalendarScreen> {
),
),
// CONTENT: calendar card overlapped on gradient, then summary and list
Column(
children: [
const SizedBox(height: 110), // leave space for appbar + some gradient top
_calendarCard(context), // calendar card sits visually on top of the gradient
_selectedDateSummary(context),
Expanded(
child: _loadingDay
? Center(child: CircularProgressIndicator(color: theme.colorScheme.primary))
: _eventsOfDay.isEmpty
? Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.event_available, size: 48, color: theme.hintColor),
const SizedBox(height: 10),
Text('No events scheduled for this date', style: theme.textTheme.bodyMedium?.copyWith(color: theme.hintColor)),
],
),
)
: ListView.builder(
padding: const EdgeInsets.only(top: 6, bottom: 32),
itemCount: _eventsOfDay.length,
itemBuilder: (context, idx) => _eventCardMobile(_eventsOfDay[idx]),
),
),
// CONTENT: whole page scrolls as one — calendar + summary + events
CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: [
// Space for app bar + gradient top
const SliverToBoxAdapter(child: SizedBox(height: 110)),
// Calendar card
SliverToBoxAdapter(child: _calendarCard(context)),
// Selected date summary
SliverToBoxAdapter(child: _selectedDateSummary(context)),
// Events area — loading / empty / list
if (_loadingDay)
SliverFillRemaining(
hasScrollBody: false,
child: Center(
child: CircularProgressIndicator(color: theme.colorScheme.primary),
),
)
else if (_eventsOfDay.isEmpty)
SliverFillRemaining(
hasScrollBody: false,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.event_available, size: 48, color: theme.hintColor),
const SizedBox(height: 10),
Text(
'No events scheduled for this date',
style: theme.textTheme.bodyMedium?.copyWith(color: theme.hintColor),
),
],
),
),
)
else
SliverList(
delegate: SliverChildBuilderDelegate(
(context, idx) => _eventCardMobile(_eventsOfDay[idx]),
childCount: _eventsOfDay.length,
),
),
// Bottom padding
const SliverToBoxAdapter(child: SizedBox(height: 32)),
],
),
],