-
Flutter_12. DatePicker> Frontend/Flutter 2023. 5. 6. 13:02
0) 학습 내용
- DatePicker를 사용하여 선택된 Date를 저장하기.
1) 완성된 코드
import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; final formatter = DateFormat.yMd(); class NewExpense extends StatefulWidget { const NewExpense({Key? key}) : super(key: key); @override State<NewExpense> createState() => _NewExpenseState(); } class _NewExpenseState extends State<NewExpense> { // => currently no need var _enteredTitle = ''; void _saveTitleInput(String inputValue) { // since there is no change in UI, no need to use setState. => currently no need _enteredTitle = inputValue; } // need to tell Flutter to delete TextEditingController when this modal is closed => otherwise, way of wasting memory. final _titleController = TextEditingController(); final _amountController = TextEditingController(); DateTime? _selectedDate; Future<void> _presentDatePicker() async { final now = DateTime.now(); final firstDate = DateTime(now.year - 1, now.month, now.day); // showDatePicker => Flutter's Date picker Method final pickedDate = await showDatePicker( context: context, initialDate: now, firstDate: firstDate, lastDate: now); // => showDatePicker return value of type 'future' // => need to async await or then method setState(() { _selectedDate = pickedDate; }); } @override void dispose() { // dispose is a part of StatefulWidget lifecycle. called when widget is destroyed. _titleController.dispose(); _amountController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(16), child: Column( children: [ TextField( // onChanged: _saveTitleInput, // first way of storing text value => onChanged controller: _titleController, // second way of storing text value => controller maxLength: 50, keyboardType: TextInputType.text, // input tag type in JS decoration: const InputDecoration( label: Text('Title')), // title of input (Text Field) ), Row( children: [ Expanded( child: TextField( // TextField wants to take as much space horizontally as possible, and Row do not restrict the amount of space which will cause error => Expanded controller: _amountController, keyboardType: TextInputType.number, decoration: const InputDecoration( // 앞에 붙는 $ 표시 prefixText: '\$ ', // title of input (Text Field) label: Text('Amount')), ), ), const SizedBox(width: 16), Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.end, // row controls the horizontal alignment to push content to the end crossAxisAlignment: CrossAxisAlignment.center, // center the content vertically. children: [ Text( _selectedDate == null ? 'No Dated Date' : formatter.format( _selectedDate!), // ! assume this wont be null ), IconButton( onPressed: _presentDatePicker, icon: const Icon(Icons.calendar_month)) ], ), ) ], ), Row( children: [ TextButton( onPressed: () { // Navigator class's pop makes modal close Navigator.pop(context); }, child: const Text('Cancel')), ElevatedButton( onPressed: () { print(_titleController.text); print(_amountController.text); }, child: const Text('Save Expense')), ], ) ], ), ); } }
2) 기존에 만든 Title TextField 에 amount 와 Date 를 추가한다.
Row( children: [ Expanded( child: TextField( // TextField wants to take as much space horizontally as possible, and Row do not restrict the amount of space which will cause error => Expanded controller: _amountController, keyboardType: TextInputType.number, decoration: const InputDecoration( // 앞에 붙는 $ 표시 prefixText: '\$ ', // title of input (Text Field) label: Text('Amount')), ), ), const SizedBox(width: 16), Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.end, // row controls the horizontal alignment to push content to the end crossAxisAlignment: CrossAxisAlignment.center, // center the content vertically. children: [ Text( _selectedDate == null ? 'No Dated Date' : formatter.format( _selectedDate!), // ! assume this wont be null ), IconButton( onPressed: _presentDatePicker, icon: const Icon(Icons.calendar_month)) ], ), ) ], ),
- 한 행(Row: 가로)에 2개의 열 (Column: 세로)를 가질 예정임으로, Row로 감싸준다.
- 이때, 1) TextField 의 경우는 최대한 많은 수평적 space를 갖는데, Row는 이를 제한하지 않음으로, 에러발생 => Expanded 사용
- 또한, 2) 두번째 Row는 그안에 중첩된 Row (Text와 IconButton)을 가질 예정임으로 => Expanded 사용
- 아래 사진에서, 달력 아이콘을 선택하면 _presendDatePicker라는 함수가 실행될 예정
현재 showModalBottomSheet 상황 3) DatePicker (달력 클릭 시, _presentDatePicker 실행)
- 달력 아이콘을 클릭하면, _presentDatePicker 함수가 실행된다.
Future<void> _presentDatePicker() async { final now = DateTime.now(); final firstDate = DateTime(now.year - 1, now.month, now.day); // showDatePicker => Flutter's Date picker Method final pickedDate = await showDatePicker( context: context, initialDate: now, firstDate: firstDate, lastDate: now); // => showDatePicker return value of type 'future' // => need to async await or then method setState(() { _selectedDate = pickedDate; }); }
- showDatePicker는 달력을 보여주는 flutter 자체적인 datepicker
- 날짜를 선택하고 OK 버튼을 누르면 값을 리턴해준다.
- 이때 Return 되는 값의 타입은 Future이다.
- future는 비동기 작업의 결과이며, 미완료 || 완료 - 두 가지 상태를 가질 수 있음.
- 비동기 작업의 결과물:
- API Data 통신
- 테이터 베이스를 거쳐 CRUD
- 파일에서 데이터 읽기
- 두가지 상태:
- 미완성 (value를 생성하기 전)
비동기 함수를 호출하면 완료되지 않은 미래가 반환됩니다. 미래에는 함수의 비동기 작업이 완료되거나 오류가 발생하기를 기다리고 있습니다. - 완료(value 생성)
비동기 작업이 성공하면 future는 값(유형 Future값으로 완료) 으로, 실패하면 오류와 함께 완료.
- 미완성 (value를 생성하기 전)
- 이러한 type을 가진 future은 async-await을 통해서 작업하면 값을 받을 수 있다.
DateTime? _selectedDate;
- DateTime?으로 _selectedDate를 생성하고, setState안에 Future의 값을 대입 (UI가 변경되기 때문)
... 생략 Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.end, // row controls the horizontal alignment to push content to the end crossAxisAlignment: CrossAxisAlignment.center, // center the content vertically. children: [ Text( _selectedDate == null ? 'No Dated Date' : formatter.format( _selectedDate!), // ! assume this wont be null ), ... 생략
- 삼항 연상자를 써서 _selectedDate 가 null일 경우, No Dated Date 노출되며, null이 아닐때는 intl의 formatter를 사용해서 _selectedDate을 y-M-d 형태로 format한다.
- 이때, Dart는 해당 일자가 null일 수도 있다고 가정해서, _selectedDate 뒤에 느낌표를 붙여 절대 null이 안된다고 가정
'> Frontend > Flutter' 카테고리의 다른 글
Flutter_14. Dropdown and Validation (0) 2023.05.09 Flutter_13. Dropdown and Validation (0) 2023.05.08 Flutter_11. App bar & Modal &Text Field (Input tag) (0) 2023.05.04 Flutter_10. Custom List & Formatting Data (0) 2023.05.03 Flutter_09.Enums and ListView (0) 2023.05.02