|
21 | 21 | - [Prerequisites? 📝](#prerequisites-)
|
22 | 22 | - [0. Project setup](#0-project-setup)
|
23 | 23 | - [1. Setting up both pages](#1-setting-up-both-pages)
|
24 |
| - - [2. `Material` Date/Time Pickers](#2-material-datetime-pickers) |
| 24 | + - [2. (Option 1) `Material` Date/Time Pickers](#2-option-1-material-datetime-pickers) |
| 25 | + - [2.1 Editing **date** and **time** separately](#21-editing-date-and-time-separately) |
| 26 | + - [2.2 Editing **date** and **time** with single button](#22-editing-date-and-time-with-single-button) |
25 | 27 |
|
26 | 28 |
|
27 | 29 | # Why? 🤷
|
@@ -204,7 +206,251 @@ Awesome!
|
204 | 206 | Now we're ready to rock 🎸!
|
205 | 207 |
|
206 | 208 |
|
207 |
| -## 2. `Material` Date/Time Pickers |
| 209 | +## 2. (Option 1) `Material` Date/Time Pickers |
208 | 210 |
|
| 211 | +Let's go over the first option, |
| 212 | +which is arguably the most "mainstream" and common approach |
| 213 | +when it comes to editing `DateTime` objects. |
209 | 214 |
|
| 215 | +With [`showDatePicker`](https://api.flutter.dev/flutter/material/showDatePicker.html) |
| 216 | +and [`TimePicker`](https://api.flutter.dev/flutter/material/showTimePicker.html), |
| 217 | +we can respectively spawn a Material Design date and time picker, |
| 218 | +respectively. |
| 219 | + |
| 220 | +Let's see how this happens! |
| 221 | +Before implementing, |
| 222 | +we're going to be using the |
| 223 | +[`intl`](https://pub.dev/packages/intl) |
| 224 | +package to correctly format the `DateTime` object |
| 225 | +that is going to be shown and mutated. |
| 226 | + |
| 227 | +Run `dart pub add intl` |
| 228 | +and wait for the dependency to download. |
| 229 | + |
| 230 | +After this, create `lib/material.dart`. |
| 231 | +This file will contain the Material example page. |
| 232 | + |
| 233 | + |
| 234 | +### 2.1 Editing **date** and **time** separately |
| 235 | + |
| 236 | +Head over to `lib/material.dart` |
| 237 | +and add the following code: |
| 238 | + |
| 239 | +```dart |
| 240 | +import 'package:flutter/material.dart'; |
| 241 | +import 'package:intl/intl.dart'; |
| 242 | +
|
| 243 | +/// Material example page. |
| 244 | +/// Showcases the usage of `DatePicker` and `TimePicker` to change date and time. |
| 245 | +class MaterialExamplePage extends StatefulWidget { |
| 246 | + const MaterialExamplePage({super.key}); |
| 247 | +
|
| 248 | + @override |
| 249 | + State<MaterialExamplePage> createState() => _MaterialExamplePageState(); |
| 250 | +} |
| 251 | +
|
| 252 | +class _MaterialExamplePageState extends State<MaterialExamplePage> { |
| 253 | + DateTime dateTime = DateTime.now(); |
| 254 | +
|
| 255 | + /// Opens date picker and returns possible `DateTime` object. |
| 256 | + Future<DateTime?> pickDate() => showDatePicker(context: context, initialDate: dateTime, firstDate: DateTime(1900), lastDate: DateTime(2100)); |
| 257 | +
|
| 258 | + /// Opens time picker and returns possible `TimeOfDay` object. |
| 259 | + Future<TimeOfDay?> pickTime() => showTimePicker(context: context, initialTime: TimeOfDay(hour: dateTime.hour, minute: dateTime.minute)); |
| 260 | +
|
| 261 | +
|
| 262 | + @override |
| 263 | + Widget build(BuildContext context) { |
| 264 | + return Container( |
| 265 | + child: Padding( |
| 266 | + padding: const EdgeInsets.only(right: 8.0, left: 8.0), |
| 267 | + child: Column( |
| 268 | + mainAxisAlignment: MainAxisAlignment.center, |
| 269 | + children: [ |
| 270 | + Row( |
| 271 | + mainAxisAlignment: MainAxisAlignment.center, |
| 272 | + children: [ |
| 273 | + Text( |
| 274 | + DateFormat('yyyy-MM-dd').format(dateTime), |
| 275 | + style: const TextStyle(fontSize: 30, fontWeight: FontWeight.bold), |
| 276 | + ), |
| 277 | + Text( |
| 278 | + DateFormat(' kk:mm').format(dateTime), |
| 279 | + style: const TextStyle(fontSize: 30), |
| 280 | + ), |
| 281 | + ], |
| 282 | + ), |
| 283 | + Padding( |
| 284 | + padding: const EdgeInsets.only(top: 16.0), |
| 285 | + child: Row( |
| 286 | + mainAxisAlignment: MainAxisAlignment.spaceEvenly, |
| 287 | + children: [ |
| 288 | + ElevatedButton( |
| 289 | + style: ElevatedButton.styleFrom(backgroundColor: Colors.blue.shade300), |
| 290 | + child: const Text( |
| 291 | + "Date", |
| 292 | + style: TextStyle(fontSize: 20), |
| 293 | + ), |
| 294 | + onPressed: () async { |
| 295 | + final newDate = await pickDate(); |
| 296 | + if (newDate == null) return; // person pressed 'CANCEL' |
| 297 | +
|
| 298 | + // Update datetime object that's shown with new date |
| 299 | + final newDateTime = DateTime(newDate.year, newDate.month, newDate.day, dateTime.hour, dateTime.minute); |
| 300 | + setState( |
| 301 | + () => dateTime = newDateTime, |
| 302 | + ); |
| 303 | + }), |
| 304 | + ElevatedButton( |
| 305 | + style: ElevatedButton.styleFrom(backgroundColor: Colors.blue.shade300), |
| 306 | + child: const Text( |
| 307 | + "Time", |
| 308 | + style: TextStyle(fontSize: 20), |
| 309 | + ), |
| 310 | + onPressed: () async { |
| 311 | + final newTime = await pickTime(); |
| 312 | + if (newTime == null) return; // person pressed 'CANCEL' |
| 313 | +
|
| 314 | + // Update datetime object that's shown with new time |
| 315 | + final newDateTime = DateTime(dateTime.year, dateTime.month, dateTime.day, newTime.hour, newTime.minute); |
| 316 | + setState( |
| 317 | + () => dateTime = newDateTime, |
| 318 | + ); |
| 319 | + }) |
| 320 | + ], |
| 321 | + ), |
| 322 | + ), |
| 323 | + ], |
| 324 | + ), |
| 325 | + ), |
| 326 | + ); |
| 327 | + } |
| 328 | +} |
| 329 | +``` |
| 330 | + |
| 331 | +Let's break down the code we've implemented. |
| 332 | + |
| 333 | +- we've created a *stateful widget page* called `MaterialExamplePage` |
| 334 | +which will be the page being shown when the person |
| 335 | +selects the `Material` option in the bottom navigation bar. |
| 336 | +- inside `_MaterialExamplePageState`, |
| 337 | +we have a `DateTime` field, |
| 338 | +which pertains to the [`DateTime`](https://api.flutter.dev/flutter/dart-core/DateTime-class.html) |
| 339 | +object being shown and edited by the person. |
| 340 | +- we've created **`pickDate`** and **`pickTime`** |
| 341 | +functions that, when invoked, |
| 342 | +use `showDatePicker` and `showTimePicker`, respectively. |
| 343 | +Calling these functions will show the picker widget dialogue. |
| 344 | +- we are using the [`DateFormat`](https://api.flutter.dev/flutter/intl/DateFormat-class.html) |
| 345 | +class from `intl` package |
| 346 | +to correctly format the `dateTime` object |
| 347 | +and show it to the person. |
| 348 | +- we are rendering two `ElevatedButtons` |
| 349 | +that call `pickDate` and `pickTime` functions. |
| 350 | + |
| 351 | +Now, we just need to use this page |
| 352 | +in `lib/main.dart`. |
| 353 | +Change the `_pages` field so it uses this newly created page. |
| 354 | + |
| 355 | +```dart |
| 356 | +final List<Widget> _pages = <Widget>[ |
| 357 | + const MaterialExamplePage(), |
| 358 | + const Text( |
| 359 | + 'Inline widget', |
| 360 | + style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold), |
| 361 | + ) |
| 362 | +]; |
| 363 | +``` |
| 364 | + |
| 365 | +If we run the app, |
| 366 | +we'll be able to *separately* |
| 367 | +set the date and the time components |
| 368 | +of the `dateTime` object. |
| 369 | + |
| 370 | + |
| 371 | +<p align='center'> |
| 372 | + <img width="250" src="https://github.com/dwyl/flutter-date-time-tutorial/assets/17494745/81701f8d-3e32-42b4-958c-486e0303b67f"> |
| 373 | +</p> |
| 374 | + |
| 375 | + |
| 376 | +### 2.2 Editing **date** and **time** with single button |
| 377 | + |
| 378 | +Instead of having separate buttons |
| 379 | +to edit the `date` and `time` in an isolated manner, |
| 380 | +let's change both at the same time by just clicking a single button. |
| 381 | + |
| 382 | +For this, add a new `ElevatedButton` below the ones |
| 383 | +we've already added. |
| 384 | + |
| 385 | +```dart |
| 386 | +@override |
| 387 | + Widget build(BuildContext context) { |
| 388 | + return Container( |
| 389 | + child: Padding( |
| 390 | + padding: const EdgeInsets.only(right: 8.0, left: 8.0), |
| 391 | + child: Column( |
| 392 | + mainAxisAlignment: MainAxisAlignment.center, |
| 393 | + children: [ |
| 394 | + // Other widgets... |
| 395 | +
|
| 396 | + // Add this line |
| 397 | + Padding( |
| 398 | + padding: const EdgeInsets.only(top: 16.0), |
| 399 | + child: Row( |
| 400 | + mainAxisAlignment: MainAxisAlignment.spaceEvenly, |
| 401 | + children: [ |
| 402 | + ElevatedButton( |
| 403 | + style: ElevatedButton.styleFrom(backgroundColor: Colors.orange.shade400), |
| 404 | + onPressed: pickDateTime, |
| 405 | + child: const Text( |
| 406 | + "DateTime", |
| 407 | + style: TextStyle(fontSize: 20), |
| 408 | + )), |
| 409 | + ], |
| 410 | + ), |
| 411 | + ) |
| 412 | + ], |
| 413 | + ), |
| 414 | + ), |
| 415 | + ); |
| 416 | + } |
| 417 | +``` |
| 418 | + |
| 419 | +Let's implement the `pickDateTime` function. |
| 420 | +In the same class `_MaterialExamplePageState`, |
| 421 | +create this function above the `build` one. |
| 422 | + |
| 423 | +```dart |
| 424 | + /// Opens date picker and time picker consecutively and sets the `DateTime` field of the page. |
| 425 | + Future pickDateTime() async { |
| 426 | + DateTime? date = await pickDate(); |
| 427 | + if (date == null) return; // pressed 'CANCEL' |
| 428 | +
|
| 429 | + TimeOfDay? time = await pickTime(); |
| 430 | + if (time == null) return; // pressed 'CANCEL' |
| 431 | +
|
| 432 | + // Update datetime object that's shown with new date |
| 433 | + final newDateTime = DateTime(date.year, date.month, date.day, time.hour, time.minute); |
| 434 | + setState( |
| 435 | + () => dateTime = newDateTime, |
| 436 | + ); |
| 437 | + } |
| 438 | +``` |
| 439 | + |
| 440 | +As you can see, |
| 441 | +we are simply calling the functions |
| 442 | +we've already implemented (`pickDate` and `pickTime`) |
| 443 | +and are updating the `dateTime` field accordingly. |
| 444 | +Pretty simple, right? |
| 445 | + |
| 446 | +Run the app and click the `DateTime` button |
| 447 | +we've just added. |
| 448 | +You should be able to set both *date* and *time*. |
| 449 | + |
| 450 | + |
| 451 | +<p align='center'> |
| 452 | + <img width="250" src="https://github.com/dwyl/flutter-date-time-tutorial/assets/17494745/177751aa-408f-4887-9b7e-64f72b0d4351"> |
| 453 | +</p> |
| 454 | + |
| 455 | +Great job! 🥳 |
210 | 456 |
|
0 commit comments