Skip to content

Instantly share code, notes, and snippets.

@tjamet
Last active November 7, 2025 00:07
Show Gist options
  • Select an option

  • Save tjamet/b863b3e4f30eca66df4cb5f0b76b9466 to your computer and use it in GitHub Desktop.

Select an option

Save tjamet/b863b3e4f30eca66df4cb5f0b76b9466 to your computer and use it in GitHub Desktop.
flutter-assertion
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(title: "test", home: CalendarScreen());
}
}
class CalendarScreen extends StatefulWidget {
const CalendarScreen({super.key});
@override
State<CalendarScreen> createState() => _CalendarScreenState();
}
class _CalendarScreenState extends State<CalendarScreen> {
int selectedChildIndex = 0;
late DateTime visibleMonth;
late DateTime selectedDate;
int viewIndex = 0; // 0: Calendar, 1: List
late final DraggableScrollableController _sheetController;
@override
void initState() {
super.initState();
final DateTime now = DateTime.now();
visibleMonth = DateTime(now.year, now.month, 1);
selectedDate = DateTime(now.year, now.month, now.day);
_sheetController = DraggableScrollableController();
}
@override
void dispose() {
_sheetController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Calendar')),
body: _buildBody(context),
);
}
Widget _buildBody(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: LayoutBuilder(
builder: (context, constraints) {
return Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildCalendar(context),
const SizedBox(height: 12),
],
),
// Placeholder(),
Positioned(
left: 0,
right: 0,
bottom: 0,
top: 0,
child: _buildEventsBottomSheet(context),
),
],
);
},
),
),
],
);
}
Widget _buildCalendar(BuildContext context) {
final DateTime firstOfMonth = DateTime(
visibleMonth.year,
visibleMonth.month,
1,
);
final int daysInMonth = DateUtils.getDaysInMonth(
visibleMonth.year,
visibleMonth.month,
);
final int firstWeekday = firstOfMonth.weekday; // 1 Mon - 7 Sun
final int leadingEmpty = (firstWeekday - 1); // make Sunday as 0 leading
final List<Widget> dayCells = [];
// Weekday labels
const List<String> weekdays = ['M', 'T', 'W', 'T', 'F', 'S', 'S'];
dayCells.addAll(
weekdays
.map(
(d) => Center(
child: Text(
d,
style: Theme.of(
context,
).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.bold),
),
),
)
.toList(),
);
// Leading blanks
for (int i = 0; i < leadingEmpty; i++) {
dayCells.add(const SizedBox.shrink());
}
// Days
for (int day = 1; day <= daysInMonth; day++) {
final DateTime date = DateTime(
visibleMonth.year,
visibleMonth.month,
day,
);
dayCells.add(
GestureDetector(
onTap: () {
setState(() {
selectedDate = date;
});
// _scheduleSheetCollapse();
},
child: Container(
margin: const EdgeInsets.all(4),
decoration: BoxDecoration(
color: Colors.orange.shade100,
borderRadius: BorderRadius.circular(8),
//border: border,
),
child: Stack(
children: [
Center(
child: Text(
'$day',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
//color: textColor,
fontWeight: FontWeight.w600,
),
),
),
],
),
),
),
);
}
// Grid: 7 columns, auto rows
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Column(
children: [
GridView.count(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
crossAxisCount: 7,
children: dayCells,
),
],
),
);
}
Widget _buildEventsBottomSheet(BuildContext context) {
final ThemeData theme = Theme.of(context);
final double minChildSize = 0.15;
final double initialChildSize = 0.3;
return DraggableScrollableSheet(
key: ValueKey<DateTime>(selectedDate),
controller: _sheetController,
minChildSize: minChildSize,
initialChildSize: initialChildSize,
maxChildSize: 0.8,
expand: false,
builder: (context, scrollController) {
return Container(
alignment: Alignment.bottomCenter,
decoration: BoxDecoration(
color: theme.colorScheme.surface,
borderRadius: const BorderRadius.vertical(top: Radius.circular(24)),
boxShadow: const [
BoxShadow(
color: Color(0x14000000),
offset: Offset(0, -4),
blurRadius: 16,
),
],
),
child: Placeholder(),
);
},
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment