英文:
How to use Flutter Riverpod with Date Range Picker
问题
我正在尝试将Flutter Riverpod与日期范围选择器一起使用。
- 我有一个Trips列表,当单击时,会打开Trip Page。
- 在Trip页面上,用户可以查看开始/结束日期。
- 然后,他们可以单击一个按钮,打开日期范围选择器小部件。
- 我希望用户能够更改日期范围,并在屏幕上反映出来(最终保存到Trip对象中)。
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
void main() {
runApp(
const ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Riverpod DateRange Picker',
home: HomeScreen(),
);
}
}
class Trip {
final String name;
final DateTimeRange dateTimeRange;
Trip(this.name, this.dateTimeRange);
}
class HomeScreen extends ConsumerWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
Set<Trip> trips = {
Trip('Test 1',
DateTimeRange(start: DateTime(2023, 1, 3), end: DateTime(2023, 1, 6)))
};
return Scaffold(
appBar: AppBar(title: const Text('Riverpod DateRange Picker')),
body: ListView(
children: [
for (final trip in trips)
ListTile(
title: Text(trip.name),
onTap: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (BuildContext context) =>
TripScreen(trip: trip)));
},
),
],
),
);
}
}
class TripScreen extends ConsumerWidget {
const TripScreen({Key? key, required this.trip}) : super(key: key);
final Trip trip;
@override
Widget build(BuildContext context, WidgetRef ref) {
void _showDateRangePicker() async {
final DateTimeRange? result = await showDateRangePicker(
context: context,
locale: const Locale('en', 'GB'),
initialDateRange: trip.dateTimeRange,
saveText: 'Done',
firstDate: DateTime(2022, 1, 1),
lastDate: DateTime(2030, 12, 31),
);
if (result != null) {
print(result);
}
}
return WillPopScope(
onWillPop: () {
Navigator.pop(context);
return Future.value(false);
},
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text(trip.name),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
IconButton(
icon: const Icon(Icons.calendar_month),
onPressed: () {
_showDateRangePicker();
},
),
Text(
'Start: ${DateFormat('dd/MM/yyyy').format(trip.dateTimeRange.start)}'),
Text(
'End: ${DateFormat('dd/MM/yyyy').format(trip.dateTimeRange.end)}'),
],
))));
}
}
任何帮助将不胜感激。
谢谢。
我已经使用Provider创建了这个,但我想使用Riverpod。
英文:
I am trying to use Flutter Riverpod together with the Date Range Picker.
- I have a list of Trips which when clicked on, open up the Trip Page.
- On the trip page, the user can view the start / end dates
- They can then click on a button, which brings up the Date Range Picker widget
- I want the user to be able to change the date range, and this be reflected on the screen (and eventually saved back against the Trip object)
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
void main() {
runApp(
const ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Riverpod DateRange Picker',
home: HomeScreen(),
);
}
}
class Trip {
final String name;
final DateTimeRange dateTimeRange;
Trip(this.name, this.dateTimeRange);
}
class HomeScreen extends ConsumerWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
Set<Trip> trips = {
Trip('Test 1',
DateTimeRange(start: DateTime(2023, 1, 3), end: DateTime(2023, 1, 6)))
};
return Scaffold(
appBar: AppBar(title: const Text('Riverpod DateRange Picker')),
body: ListView(
children: [
for (final trip in trips)
ListTile(
title: Text(trip.name),
onTap: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (BuildContext context) =>
TripScreen(trip: trip)));
},
),
],
),
);
}
}
class TripScreen extends ConsumerWidget {
const TripScreen({Key? key, required this.trip}) : super(key: key);
final Trip trip;
@override
Widget build(BuildContext context, WidgetRef ref) {
void _showDateRangePicker() async {
final DateTimeRange? result = await showDateRangePicker(
context: context,
locale: const Locale('en', 'GB'),
initialDateRange: trip.dateTimeRange,
saveText: 'Done',
firstDate: DateTime(2022, 1, 1),
lastDate: DateTime(2030, 12, 31),
);
if (result != null) {
print(result);
}
}
return WillPopScope(
onWillPop: () {
Navigator.pop(context);
return Future.value(false);
},
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text(trip.name),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
IconButton(
icon: const Icon(Icons.calendar_month),
onPressed: () {
_showDateRangePicker();
},
),
Text(
'Start: ${DateFormat('dd/MM/yyyy').format(trip.dateTimeRange.start)}'),
Text(
'End: ${DateFormat('dd/MM/yyyy').format(trip.dateTimeRange.end)}'),
],
))));
}
}
Any help would be much appriciated.
Thanks.
I've created this using Provider but I would like to use Riverpod.
答案1
得分: 1
我创建了一个 "tripsProvider" 实例,它是 StateProvider 的实例,用于保存所有的旅行数据,就像在你的情况下只有一个值。主屏幕观察该提供程序并在 ListView 中显示数据,当用户在列表中选择项目时,我传递项目的索引,并在新屏幕上(与你的 TripScreen 类似的屏幕副本)观察该单个项目。当用户更新单个项目的数据时,我更新了列表,因此在 TripScreen 和 HomeScreen 上都可以看到更新。我仍在学习 riverpod,但希望我的答案能帮到你。
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
void main() {
runApp(
const ProviderScope(
child: MyApp(),
),
);
}
final tripsProvider = StateProvider<List<Trip>>(
(ref) => [
Trip(
'Test 1',
DateTimeRange(start: DateTime(2023, 1, 3), end: DateTime(2023, 1, 6)),
),
],
);
class Trip {
final String name;
final DateTimeRange dateTimeRange;
const Trip(this.name, this.dateTimeRange);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Riverpod DateRange Picker',
home: HomeScreen(),
);
}
}
class HomeScreen extends ConsumerWidget {
const HomeScreen({Key? key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final trips = ref.watch(tripsProvider);
return Scaffold(
appBar: AppBar(title: const Text('Riverpod DateRange Picker')),
body: ListView.builder(
itemCount: trips.length,
itemBuilder: (context, index) {
Trip trip = trips[index];
return ListTile(
title: Text(trip.name),
onTap: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (BuildContext context) => TripScreen(index: index),
),
);
},
);
},
),
);
}
}
class TripScreen extends ConsumerWidget {
int index;
TripScreen({Key? key, required this.index}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final trip = ref.watch(tripsProvider)[index];
void _showDateRangePicker() async {
final DateTimeRange? result = await showDateRangePicker(
context: context,
locale: const Locale('en', 'GB'),
initialDateRange: trip.dateTimeRange,
saveText: 'Done',
firstDate: DateTime(2022, 1, 1),
lastDate: DateTime(2030, 12, 31),
);
if (result != null) {
print(result);
Trip updatedTrip = Trip(trip.name, DateTimeRange(start: result.start, end: result.end));
ref.read(tripsProvider.notifier).update(
(state) {
List<Trip> updatedList = [];
for (int i = 0; i < state.length; i++) {
if (i == index) {
updatedList.add(updatedTrip);
} else {
updatedList.add(state[i]);
}
}
return updatedList;
},
);
}
}
return WillPopScope(
onWillPop: () {
Navigator.pop(context);
return Future.value(false);
},
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text(trip.name),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
IconButton(
icon: const Icon(Icons.calendar_month),
onPressed: () {
_showDateRangePicker();
},
),
Text('Start: ${DateFormat('dd/MM/yyyy').format(trip.dateTimeRange.start)}'),
Text('End: ${DateFormat('dd/MM/yyyy').format(trip.dateTimeRange.end)}'),
],
),
),
),
);
}
}
英文:
I created "tripsProvider" instance of StateProvider that holds all trip data, like in your case only one value. Home screen watching that provider and displaying data in ListView, when user select item in list I pass index of item and watch that single item on new screen (copy of yours TripScreen).
When user update the data of single item I update that list, so update is available on TripScreen and HomeScreen. I also still learning riverpod but hope my answer can help you.
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
void main() {
runApp(
const ProviderScope(
child: MyApp(),
),
);
}
final tripsProvider = StateProvider<List<Trip>>(
(ref) => [
Trip(
'Test 1',
DateTimeRange(start: DateTime(2023, 1, 3), end: DateTime(2023, 1, 6)),
),
],
);
class Trip {
final String name;
final DateTimeRange dateTimeRange;
const Trip(this.name, this.dateTimeRange);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Riverpod DateRange Picker',
home: HomeScreen(),
);
}
}
class HomeScreen extends ConsumerWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final trips = ref.watch(tripsProvider);
return Scaffold(
appBar: AppBar(title: const Text('Riverpod DateRange Picker')),
body: ListView.builder(
itemCount: trips.length,
itemBuilder: (context, index) {
Trip trip = trips[index];
return ListTile(
title: Text(trip.name),
onTap: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (BuildContext context) => TripScreen(index: index),
),
);
},
);
},
),
);
}
}
class TripScreen extends ConsumerWidget {
int index;
TripScreen({Key? key, required this.index}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final trip = ref.watch(tripsProvider)[index];
void _showDateRangePicker() async {
final DateTimeRange? result = await showDateRangePicker(
context: context,
locale: const Locale('en', 'GB'),
initialDateRange: trip.dateTimeRange,
saveText: 'Done',
firstDate: DateTime(2022, 1, 1),
lastDate: DateTime(2030, 12, 31),
);
if (result != null) {
print(result);
Trip updatedTrip = Trip(trip.name, DateTimeRange(start: result.start, end: result.end));
ref.read(tripsProvider.notifier).update(
(state) {
List<Trip> updatedList = [];
for (int i = 0; i < state.length; i++) {
if (i == index) {
updatedList.add(updatedTrip);
} else {
updatedList.add(state[i]);
}
}
return updatedList;
},
);
}
}
return WillPopScope(
onWillPop: () {
Navigator.pop(context);
return Future.value(false);
},
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text(trip.name),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
IconButton(
icon: const Icon(Icons.calendar_month),
onPressed: () {
_showDateRangePicker();
},
),
Text('Start: ${DateFormat('dd/MM/yyyy').format(trip.dateTimeRange.start)}'),
Text('End: ${DateFormat('dd/MM/yyyy').format(trip.dateTimeRange.end)}'),
],
),
),
),
);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论