Я пытаюсь создать страницу, похожую на дневной вид Календаря Google во Флаттере.
Пример Календаря Google
Вот упрощенный исполняемый файл версия моего текущего кода (в качестве дополнительной зависимости требуется "table_calendar: ^ 0.1.3"):
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:math';
import 'package:table_calendar/table_calendar.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: [const Locale('en')],
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MonthPage(),
);
}
}
class MonthPage extends StatefulWidget {
MonthPage({key}) : super(key: key);
State<MonthPage> createState() => MonthPageState();
}
class MonthPageState extends State<MonthPage> with TickerProviderStateMixin {
CalendarController _calendarController;
ScrollController _scrollController;
DateTime _selectedDate;
bool _isExpanded;
double _rotationDegree;
@override
void initState() {
_isExpanded = false;
_rotationDegree = 0;
_selectedDate = DateTime.now();
_calendarController = CalendarController();
_scrollController = ScrollController();
_scrollController.addListener(_scrollListner);
super.initState();
}
void _scrollListner() {
setState(() {
if (_isExpanded) {
double rotationDegree = pi * _scrollController.offset / 212;
if (rotationDegree >= pi) {
_rotationDegree = 0;
_isExpanded = !_isExpanded;
} else {
_rotationDegree = rotationDegree;
}
}
});
}
@override
void dispose() {
_calendarController.dispose();
_scrollController.dispose();
super.dispose();
}
_toogleExpand() {
setState(() {
_isExpanded = !_isExpanded;
});
}
Widget GetAppBarTitle() {
return Row(
children: <Widget>[
Text("${_selectedDate}"),
Transform.rotate(
angle: _rotationDegree,
child: IconButton(
icon: Icon(
_isExpanded ? Icons.arrow_drop_up : Icons.arrow_drop_down),
onPressed: () {
_toogleExpand();
},
)),
],
);
}
Widget ShowCalendar() {
if (_isExpanded) {
return TableCalendar(
rowHeight: 37,
locale: "de_DE",
calendarStyle: CalendarStyle(
contentPadding: EdgeInsets.only(top: 7),
weekdayStyle: TextStyle(
fontSize: 12,
),
weekendStyle: TextStyle(fontSize: 12)),
calendarController: _calendarController,
startingDayOfWeek: StartingDayOfWeek.monday,
headerVisible: false,
onVisibleDaysChanged: (first, last, format) {
setState(() {
_selectedDate = last;
});
},
onDaySelected: (date, events) {
setState(() {
_selectedDate = date;
});
},
);
} else {
return SizedBox.shrink();
}
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: CustomScrollView(
controller: _scrollController,
slivers: <Widget>[
SliverAppBar(pinned: true, title: GetAppBarTitle()),
SliverToBoxAdapter(child: ShowCalendar()),
SliverToBoxAdapter(
child: Container(height: 0.1, child: Material(child: Divider()))),
SliverPadding(
padding: EdgeInsets.only(top: 10),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) =>
InkWell(child: Text("My list item ${index}")),
childCount: 70),
))
],
),
);
}
}
Теперь у меня есть следующая проблема :
Когда пользователь прокручивает страницу вниз и открывает календарь (выпадающий значок), календарь должен быть виден и соответствующая позиция списка должна сохраняться. В настоящее время календарь отображается за пределами области, видимой пользователю перед списком.
Я уже пытался вставить календарь в SliverAppBar в качестве фона в FlexibleSpace, но затем календарь пересекается с заголовком при прокрутке вверх.
Я благодарен за любую помощь.