如何在 flutter 中更改此日历小部件中的选定日期?
How can I change the selected date in this calendar widget in flutter?
我正在尝试制作一个可以选择一个日期的日历小部件,我可以使用硬编码设置所选日期,但我希望能够从内部小部件 (DayWidget) 更改所选日期。
我的代码:
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class HorizontalCalendar extends StatefulWidget {
final double height;
final double width;
final EdgeInsets padding;
final EdgeInsets margin;
final int month;
final int year;
final int selectedDate;
HorizontalCalendar({
@required this.year,
@required this.month,
this.selectedDate,
this.height,
this.width,
this.margin = const EdgeInsets.all(0),
this.padding = const EdgeInsets.all(0),
});
@override
_HorizontalCalendarState createState() => _HorizontalCalendarState();
}
class _HorizontalCalendarState extends State<HorizontalCalendar> {
@override
Widget build(BuildContext context) {
return Container(
width: widget.width,
height: widget.height,
margin: widget.margin,
padding: widget.padding,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: DateTime(widget.year, widget.month + 1, 0).day,
itemBuilder: (context, index) {
index = index + 1;
DateTime date = DateTime(widget.year, widget.month, index);
return DayWidget(
day: index,
dayName: DateFormat('EEEE').format(date).substring(0, 3),
selected: widget.selectedDate == index ? true : false,
);
},
),
);
}
}
日小部件:
class DayWidget extends StatelessWidget {
final int day;
final String dayName;
final bool selected;
DayWidget({this.day, this.dayName, this.selected = false});
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 5),
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.17,
child: FlatButton(
color: selected ? Colors.white : Colors.transparent,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(15.0),
side: BorderSide(
color: selected ? Colors.white : Colors.grey,
width: 1,
style: BorderStyle.solid)),
onPressed: () {
// Here I should be able to change the selected date from
// The HorizontalCalendar
},
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text(
dayName,
style: TextStyle(
color: selected ? Colors.blueGrey : Colors.white60,
fontSize: 15,
fontWeight: selected ? FontWeight.w900 : FontWeight.w300),
),
Text(
day.toString(),
style: TextStyle(
color: selected ? Colors.blueGrey : Colors.white,
fontSize: 24,
fontWeight: selected ? FontWeight.w900 : FontWeight.w500),
),
],
),
),
),
);
}
}
image of the widget for clarification
我试图在按下 DayWidget 时更改选定的日期,但我似乎无法访问 HorizontalCalendar 小部件,我试图将方法设置为静态,但如果我在 HorizontalCalendar 静态中设置方法,我无法使用 setState 更新视图。
请指导我更好地实现它。
- 首先我们需要移动 selectedDate 到可变变量。我们需要在
_HorizontalCalendarState
class. 上重新声明它
class HorizontalCalendar extends StatefulWidget {
final double height;
final double width;
final EdgeInsets padding;
final EdgeInsets margin;
final int month;
final int year;
final int selectedDate; // this is immutable
HorizontalCalendar({
@required this.year,
@required this.month,
this.selectedDate,
this.height,
this.width,
this.margin = const EdgeInsets.all(0),
this.padding = const EdgeInsets.all(0),
});
@override
_HorizontalCalendarState createState() => _HorizontalCalendarState();
}
class _HorizontalCalendarState extends State<HorizontalCalendar> {
int selectedDay; // this is mutable
@override
void initState() {
selectedDay = widget.selectedDate;
super.initState();
}
- 其次,我们可以将回调传递给DayWidget。
return DayWidget(
day: index,
dayName: DateFormat('EEEE').format(date).substring(0, 3),
selected: selectedDay == index ? true : false, // modify this
callback: (int day) { // Add this
selectedDay = day;
setState((){});
},
);
- 终于可以在DayWidget中回调了:
onPressed: () {
callback(day);
// Here I should be able to change the selected date from
// The HorizontalCalendar
},
这是结果:
- 完整代码
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class HorizontalCalendar extends StatefulWidget {
final double height;
final double width;
final EdgeInsets padding;
final EdgeInsets margin;
final int month;
final int year;
final int selectedDate; // this is immutable
HorizontalCalendar({
@required this.year,
@required this.month,
this.selectedDate,
this.height,
this.width,
this.margin = const EdgeInsets.all(0),
this.padding = const EdgeInsets.all(0),
});
@override
_HorizontalCalendarState createState() => _HorizontalCalendarState();
}
class _HorizontalCalendarState extends State<HorizontalCalendar> {
int selectedDay; // this is mutable
@override
void initState() {
selectedDay = widget.selectedDate;
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
width: widget.width,
height: widget.height,
margin: widget.margin,
padding: widget.padding,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: DateTime(widget.year, widget.month + 1, 0).day,
itemBuilder: (context, index) {
index = index + 1;
DateTime date = DateTime(widget.year, widget.month, index);
return DayWidget(
day: index,
dayName: DateFormat('EEEE').format(date).substring(0, 3),
selected: selectedDay == index ? true : false,
callback: (int day) {
selectedDay = day;
setState((){});
},
);
},
),
);
}
}
class DayWidget extends StatelessWidget {
final int day;
final String dayName;
final bool selected;
final Function(int) callback;
DayWidget({
this.day,
this.dayName,
this.selected = false,
this.callback,
});
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 5),
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.17,
child: FlatButton(
color: selected ? Colors.white : Colors.transparent,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(15.0),
side: BorderSide(
color: selected ? Colors.white : Colors.grey,
width: 1,
style: BorderStyle.solid),
),
onPressed: () {
callback(day);
// Here I should be able to change the selected date from
// The HorizontalCalendar
},
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text(
dayName,
style: TextStyle(
color: selected ? Colors.blueGrey : Colors.white60,
fontSize: 15,
fontWeight: selected ? FontWeight.w900 : FontWeight.w300,
),
),
Text(
day.toString(),
style: TextStyle(
color: selected ? Colors.blueGrey : Colors.white,
fontSize: 24,
fontWeight: selected ? FontWeight.w900 : FontWeight.w500,
),
),
],
),
),
),
);
}
}
我正在尝试制作一个可以选择一个日期的日历小部件,我可以使用硬编码设置所选日期,但我希望能够从内部小部件 (DayWidget) 更改所选日期。
我的代码:
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class HorizontalCalendar extends StatefulWidget {
final double height;
final double width;
final EdgeInsets padding;
final EdgeInsets margin;
final int month;
final int year;
final int selectedDate;
HorizontalCalendar({
@required this.year,
@required this.month,
this.selectedDate,
this.height,
this.width,
this.margin = const EdgeInsets.all(0),
this.padding = const EdgeInsets.all(0),
});
@override
_HorizontalCalendarState createState() => _HorizontalCalendarState();
}
class _HorizontalCalendarState extends State<HorizontalCalendar> {
@override
Widget build(BuildContext context) {
return Container(
width: widget.width,
height: widget.height,
margin: widget.margin,
padding: widget.padding,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: DateTime(widget.year, widget.month + 1, 0).day,
itemBuilder: (context, index) {
index = index + 1;
DateTime date = DateTime(widget.year, widget.month, index);
return DayWidget(
day: index,
dayName: DateFormat('EEEE').format(date).substring(0, 3),
selected: widget.selectedDate == index ? true : false,
);
},
),
);
}
}
日小部件:
class DayWidget extends StatelessWidget {
final int day;
final String dayName;
final bool selected;
DayWidget({this.day, this.dayName, this.selected = false});
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 5),
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.17,
child: FlatButton(
color: selected ? Colors.white : Colors.transparent,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(15.0),
side: BorderSide(
color: selected ? Colors.white : Colors.grey,
width: 1,
style: BorderStyle.solid)),
onPressed: () {
// Here I should be able to change the selected date from
// The HorizontalCalendar
},
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text(
dayName,
style: TextStyle(
color: selected ? Colors.blueGrey : Colors.white60,
fontSize: 15,
fontWeight: selected ? FontWeight.w900 : FontWeight.w300),
),
Text(
day.toString(),
style: TextStyle(
color: selected ? Colors.blueGrey : Colors.white,
fontSize: 24,
fontWeight: selected ? FontWeight.w900 : FontWeight.w500),
),
],
),
),
),
);
}
}
image of the widget for clarification
我试图在按下 DayWidget 时更改选定的日期,但我似乎无法访问 HorizontalCalendar 小部件,我试图将方法设置为静态,但如果我在 HorizontalCalendar 静态中设置方法,我无法使用 setState 更新视图。
请指导我更好地实现它。
- 首先我们需要移动 selectedDate 到可变变量。我们需要在
_HorizontalCalendarState
class. 上重新声明它
class HorizontalCalendar extends StatefulWidget {
final double height;
final double width;
final EdgeInsets padding;
final EdgeInsets margin;
final int month;
final int year;
final int selectedDate; // this is immutable
HorizontalCalendar({
@required this.year,
@required this.month,
this.selectedDate,
this.height,
this.width,
this.margin = const EdgeInsets.all(0),
this.padding = const EdgeInsets.all(0),
});
@override
_HorizontalCalendarState createState() => _HorizontalCalendarState();
}
class _HorizontalCalendarState extends State<HorizontalCalendar> {
int selectedDay; // this is mutable
@override
void initState() {
selectedDay = widget.selectedDate;
super.initState();
}
- 其次,我们可以将回调传递给DayWidget。
return DayWidget(
day: index,
dayName: DateFormat('EEEE').format(date).substring(0, 3),
selected: selectedDay == index ? true : false, // modify this
callback: (int day) { // Add this
selectedDay = day;
setState((){});
},
);
- 终于可以在DayWidget中回调了:
onPressed: () {
callback(day);
// Here I should be able to change the selected date from
// The HorizontalCalendar
},
这是结果:
- 完整代码
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class HorizontalCalendar extends StatefulWidget {
final double height;
final double width;
final EdgeInsets padding;
final EdgeInsets margin;
final int month;
final int year;
final int selectedDate; // this is immutable
HorizontalCalendar({
@required this.year,
@required this.month,
this.selectedDate,
this.height,
this.width,
this.margin = const EdgeInsets.all(0),
this.padding = const EdgeInsets.all(0),
});
@override
_HorizontalCalendarState createState() => _HorizontalCalendarState();
}
class _HorizontalCalendarState extends State<HorizontalCalendar> {
int selectedDay; // this is mutable
@override
void initState() {
selectedDay = widget.selectedDate;
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
width: widget.width,
height: widget.height,
margin: widget.margin,
padding: widget.padding,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: DateTime(widget.year, widget.month + 1, 0).day,
itemBuilder: (context, index) {
index = index + 1;
DateTime date = DateTime(widget.year, widget.month, index);
return DayWidget(
day: index,
dayName: DateFormat('EEEE').format(date).substring(0, 3),
selected: selectedDay == index ? true : false,
callback: (int day) {
selectedDay = day;
setState((){});
},
);
},
),
);
}
}
class DayWidget extends StatelessWidget {
final int day;
final String dayName;
final bool selected;
final Function(int) callback;
DayWidget({
this.day,
this.dayName,
this.selected = false,
this.callback,
});
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 5),
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.17,
child: FlatButton(
color: selected ? Colors.white : Colors.transparent,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(15.0),
side: BorderSide(
color: selected ? Colors.white : Colors.grey,
width: 1,
style: BorderStyle.solid),
),
onPressed: () {
callback(day);
// Here I should be able to change the selected date from
// The HorizontalCalendar
},
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text(
dayName,
style: TextStyle(
color: selected ? Colors.blueGrey : Colors.white60,
fontSize: 15,
fontWeight: selected ? FontWeight.w900 : FontWeight.w300,
),
),
Text(
day.toString(),
style: TextStyle(
color: selected ? Colors.blueGrey : Colors.white,
fontSize: 24,
fontWeight: selected ? FontWeight.w900 : FontWeight.w500,
),
),
],
),
),
),
);
}
}