如何在 Flutter 中实现 SingleLine 水平 CalendarView
Posted
技术标签:
【中文标题】如何在 Flutter 中实现 SingleLine 水平 CalendarView【英文标题】:How to achieve SingleLine Horizontal CalendarView in Flutter 【发布时间】:2020-02-02 09:29:56 【问题描述】:我是 Flutter 的新手。如何在颤动中实现SingleLine
水平滚动CalendarView
和日期选择。
请找到预期CalendarView
的下图。帮助将不胜感激
Expected CalendarView
【问题讨论】:
【参考方案1】:你可以使用包https://pub.dev/packages/table_calendar 在月份模式下,只会显示一行日期
代码sn-p
return TableCalendar(
locale: 'pl_PL',
calendarController: _calendarController,
events: _events,
holidays: _holidays,
initialCalendarFormat: CalendarFormat.month,
formatAnimation: FormatAnimation.slide,
startingDayOfWeek: StartingDayOfWeek.sunday,
availableGestures: AvailableGestures.all,
availableCalendarFormats: const
CalendarFormat.month: '',
CalendarFormat.week: '',
,
示例代码中,_buildButtons() 和 _buildEventList() 如果不需要,可以备注
body: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
// Switch out 2 lines below to play with TableCalendar's settings
//-----------------------
_buildTableCalendar(),
// _buildTableCalendarWithBuilders(),
//const SizedBox(height: 8.0),
//_buildButtons(),
//const SizedBox(height: 8.0),
//Expanded(child: _buildEventList()),
],
),
完整示例代码
// Copyright (c) 2019 Aleksander Woźniak
// Licensed under Apache License v2.0
import 'package:flutter/material.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:table_calendar/table_calendar.dart';
// Example holidays
final Map<DateTime, List> _holidays =
DateTime(2019, 1, 1): ['New Year\'s Day'],
DateTime(2019, 1, 6): ['Epiphany'],
DateTime(2019, 2, 14): ['Valentine\'s Day'],
DateTime(2019, 4, 21): ['Easter Sunday'],
DateTime(2019, 4, 22): ['Easter Monday'],
;
void main()
initializeDateFormatting().then((_) => runApp(MyApp()));
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Table Calendar Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Table Calendar Demo'),
);
class MyHomePage extends StatefulWidget
MyHomePage(Key key, this.title) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin
Map<DateTime, List> _events;
List _selectedEvents;
AnimationController _animationController;
CalendarController _calendarController;
@override
void initState()
super.initState();
final _selectedDay = DateTime.now();
_events =
_selectedDay.subtract(Duration(days: 30)): ['Event A0', 'Event B0', 'Event C0'],
_selectedDay.subtract(Duration(days: 27)): ['Event A1'],
_selectedDay.subtract(Duration(days: 20)): ['Event A2', 'Event B2', 'Event C2', 'Event D2'],
_selectedDay.subtract(Duration(days: 16)): ['Event A3', 'Event B3'],
_selectedDay.subtract(Duration(days: 10)): ['Event A4', 'Event B4', 'Event C4'],
_selectedDay.subtract(Duration(days: 4)): ['Event A5', 'Event B5', 'Event C5'],
_selectedDay.subtract(Duration(days: 2)): ['Event A6', 'Event B6'],
_selectedDay: ['Event A7', 'Event B7', 'Event C7', 'Event D7'],
_selectedDay.add(Duration(days: 1)): ['Event A8', 'Event B8', 'Event C8', 'Event D8'],
_selectedDay.add(Duration(days: 3)): Set.from(['Event A9', 'Event A9', 'Event B9']).toList(),
_selectedDay.add(Duration(days: 7)): ['Event A10', 'Event B10', 'Event C10'],
_selectedDay.add(Duration(days: 11)): ['Event A11', 'Event B11'],
_selectedDay.add(Duration(days: 17)): ['Event A12', 'Event B12', 'Event C12', 'Event D12'],
_selectedDay.add(Duration(days: 22)): ['Event A13', 'Event B13'],
_selectedDay.add(Duration(days: 26)): ['Event A14', 'Event B14', 'Event C14'],
;
_selectedEvents = _events[_selectedDay] ?? [];
_calendarController = CalendarController();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 400),
);
_animationController.forward();
@override
void dispose()
_animationController.dispose();
_calendarController.dispose();
super.dispose();
void _onDaySelected(DateTime day, List events)
print('CALLBACK: _onDaySelected');
setState(()
_selectedEvents = events;
);
void _onVisibleDaysChanged(DateTime first, DateTime last, CalendarFormat format)
print('CALLBACK: _onVisibleDaysChanged');
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
// Switch out 2 lines below to play with TableCalendar's settings
//-----------------------
_buildTableCalendar(),
// _buildTableCalendarWithBuilders(),
const SizedBox(height: 8.0),
_buildButtons(),
const SizedBox(height: 8.0),
Expanded(child: _buildEventList()),
],
),
);
// Simple TableCalendar configuration (using Styles)
Widget _buildTableCalendar()
return TableCalendar(
calendarController: _calendarController,
events: _events,
holidays: _holidays,
startingDayOfWeek: StartingDayOfWeek.monday,
calendarStyle: CalendarStyle(
selectedColor: Colors.deepOrange[400],
todayColor: Colors.deepOrange[200],
markersColor: Colors.brown[700],
outsideDaysVisible: false,
),
headerStyle: HeaderStyle(
formatButtonTextStyle: TextStyle().copyWith(color: Colors.white, fontSize: 15.0),
formatButtonDecoration: BoxDecoration(
color: Colors.deepOrange[400],
borderRadius: BorderRadius.circular(16.0),
),
),
onDaySelected: _onDaySelected,
onVisibleDaysChanged: _onVisibleDaysChanged,
);
// More advanced TableCalendar configuration (using Builders & Styles)
Widget _buildTableCalendarWithBuilders()
return TableCalendar(
locale: 'pl_PL',
calendarController: _calendarController,
events: _events,
holidays: _holidays,
initialCalendarFormat: CalendarFormat.month,
formatAnimation: FormatAnimation.slide,
startingDayOfWeek: StartingDayOfWeek.sunday,
availableGestures: AvailableGestures.all,
availableCalendarFormats: const
CalendarFormat.month: '',
CalendarFormat.week: '',
,
calendarStyle: CalendarStyle(
outsideDaysVisible: false,
weekendStyle: TextStyle().copyWith(color: Colors.blue[800]),
holidayStyle: TextStyle().copyWith(color: Colors.blue[800]),
),
daysOfWeekStyle: DaysOfWeekStyle(
weekendStyle: TextStyle().copyWith(color: Colors.blue[600]),
),
headerStyle: HeaderStyle(
centerHeaderTitle: true,
formatButtonVisible: false,
),
builders: CalendarBuilders(
selectedDayBuilder: (context, date, _)
return FadeTransition(
opacity: Tween(begin: 0.0, end: 1.0).animate(_animationController),
child: Container(
margin: const EdgeInsets.all(4.0),
padding: const EdgeInsets.only(top: 5.0, left: 6.0),
color: Colors.deepOrange[300],
width: 100,
height: 100,
child: Text(
'$date.day',
style: TextStyle().copyWith(fontSize: 16.0),
),
),
);
,
todayDayBuilder: (context, date, _)
return Container(
margin: const EdgeInsets.all(4.0),
padding: const EdgeInsets.only(top: 5.0, left: 6.0),
color: Colors.amber[400],
width: 100,
height: 100,
child: Text(
'$date.day',
style: TextStyle().copyWith(fontSize: 16.0),
),
);
,
markersBuilder: (context, date, events, holidays)
final children = <Widget>[];
if (events.isNotEmpty)
children.add(
Positioned(
right: 1,
bottom: 1,
child: _buildEventsMarker(date, events),
),
);
if (holidays.isNotEmpty)
children.add(
Positioned(
right: -2,
top: -2,
child: _buildHolidaysMarker(),
),
);
return children;
,
),
onDaySelected: (date, events)
_onDaySelected(date, events);
_animationController.forward(from: 0.0);
,
onVisibleDaysChanged: _onVisibleDaysChanged,
);
Widget _buildEventsMarker(DateTime date, List events)
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: _calendarController.isSelected(date)
? Colors.brown[500]
: _calendarController.isToday(date) ? Colors.brown[300] : Colors.blue[400],
),
width: 16.0,
height: 16.0,
child: Center(
child: Text(
'$events.length',
style: TextStyle().copyWith(
color: Colors.white,
fontSize: 12.0,
),
),
),
);
Widget _buildHolidaysMarker()
return Icon(
Icons.add_box,
size: 20.0,
color: Colors.blueGrey[800],
);
Widget _buildButtons()
return Column(
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RaisedButton(
child: Text('month'),
onPressed: ()
setState(()
_calendarController.setCalendarFormat(CalendarFormat.month);
);
,
),
RaisedButton(
child: Text('2 weeks'),
onPressed: ()
setState(()
_calendarController.setCalendarFormat(CalendarFormat.twoWeeks);
);
,
),
RaisedButton(
child: Text('week'),
onPressed: ()
setState(()
_calendarController.setCalendarFormat(CalendarFormat.week);
);
,
),
],
),
const SizedBox(height: 8.0),
RaisedButton(
child: Text('setDay 10-07-2019'),
onPressed: ()
_calendarController.setSelectedDay(DateTime(2019, 7, 10), runCallback: true);
,
),
],
);
Widget _buildEventList()
return ListView(
children: _selectedEvents
.map((event) => Container(
decoration: BoxDecoration(
border: Border.all(width: 0.8),
borderRadius: BorderRadius.circular(12.0),
),
margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
child: ListTile(
title: Text(event.toString()),
onTap: () => print('$event tapped!'),
),
))
.toList(),
);
【讨论】:
在这里,我只想显示SigleLine
并且必须从 HeaderStyle
中删除(月、周和周)选项我只想只有月,帮帮我
你的意思是availableCalendarFormats: const CalendarFormat.month: '',你只需要月份吗?你可以直接删除周
是的,我只需要一个月
initialCalendarFormat: CalendarFormat.week, availableCalendarFormats: const CalendarFormat.week: 'Week', ,
将 initialCalendarFormat: 更改为 CalendarFormat.week 并添加 availableCalendarFormats ,就可以了以上是关于如何在 Flutter 中实现 SingleLine 水平 CalendarView的主要内容,如果未能解决你的问题,请参考以下文章