반응형
오늘 만들 화면은 위와 같다.
위 화면을 구성하기 위해 할일은 다음과 같다.
- FloatingActionButton 생성
- Todo Item 추가를 위한 AlertDialog 생성
- 생성된 Todo Item을 추가하고 리스트를 갱신
어려운 것은 없으니 천천히 시작해본다.
1. TodoModel 작성
Todo Item을 표현하기 위한 TodoModel 클래스를 작성한다.
// todo_model.dart
class TodoModel {
String _title;
TodoState _state;
final DateTime _createdTime;
TodoModel(this._title, this._createdTime) {
_state = TodoState.todo;
}
String getTitle() => _title;
DateTime getCreatedTime() => _createdTime;
TodoState getTodoState() => _state;
String setTitle(String title) => _title = title;
TodoState setTodoState(TodoState state) => _state = state;
}
enum TodoState {
todo, inProgress, done
}
TodoModel은 아래 항목들을 가지고 있다.
- String _title : TodoItem의 제목을 의미한다.
- TodoState _state : TodoItem의 상태다. 할일인지, 하고 있는지, 완료되었는지를 나타낸다.
- DateTime _createdTime : TodoItem의 생성 날짜를 나타낸다.
그리고 위 속성들에 접근할 수 있는 Getter, Setter를 작성한다.
2. 날짜를 다루기 위한 패키지 추가
Flutter에서 DateTime을 우리가 원하는 포맷(yyyy-MM-dd와 같은)으로 변경하기 위해 패키지가 필요하다.
위 패키지를 추가 할 것이다.
pubspec.yaml에 추가하자.
name: ...
description: ...
publish_to: ...
version: ...
environment:
...
dependencies:
flutter:
sdk: flutter
...
intl: ^0.16.0 # 이 부분을 추가한다.
...
완료한 후 Pub get으로 패키지를 갱신해주는 것을 잊지말자!
3. TodoListPage에 FloatingActionButton 추가
class _TodoListPageState extends State<TodoListPage> {
final TextEditingController _todoTitleController = TextEditingController();
List<TodoModel> _todoList = [];
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: _createFloatingActionButton(),
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
body: _createTodoList(),
);
}
...
Widget _createFloatingActionButton() {
return FloatingActionButton(
child: Icon(Icons.add, color: Colors.white),
onPressed: () => {
_openAddTodoDialog()
},
);
}
void _openAddTodoDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)
),
title: Text(
"할일을 입력해주세요.",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24.0,
color: Colors.blue
),
),
content: TextField(
controller: _todoTitleController,
),
actions: [
FlatButton(
child: new Text(
"취소",
style: TextStyle(
fontSize: 16.0,
color: Colors.red
),
),
onPressed: () {
_todoTitleController.text = "";
Navigator.pop(context);
},
),
FlatButton(
child: new Text(
"추가",
style: TextStyle(
fontSize: 16.0,
color: Colors.blue
),
),
onPressed: () {
_addNewTodo(_todoTitleController.text);
_todoTitleController.text = "";
Navigator.pop(context);
},
),
],
);
}
);
}
void _addNewTodo(String title) {
TodoModel newTodo = TodoModel(title, DateTime.now());
setState(() {
_todoList.add(newTodo);
});
}
...
}
코드가 꽤 길지만, 단순하다.
- Scaffold에 FloatingActionButton을 생성하고 누를경우(onPressed) _openAddTodoDialog를 호출하여 AlertDialog를 보여준다.
- AlertDialog를 생성하는 코드는 위를 참고 바라며, AlertDialog를 보여주기 위해서 "showDialog" 함수에 AlertDialog를 넘겨주면 된다.
- Flutter에서 TextField로 텍스트를 입력하고 값을 받아오기 위해서 "TextEditingController" 객체를 생성하여 TextField의 controller 파라미터에 전달해주어야 하는 것을 주의한다.
- 다이얼로그의 "추가" 버튼을 누르면 _addNewTodo가 호출되며, "setState" 함수 내부에서 _todoList에 새로 생성된 TodoModel 객체를 추가한다.
4. TodoListPage의 _createTodoList 함수 변경
class _TodoListPageState extends State<TodoListPage> {
static const String TODO_DATE_FORMAT = "yyy-MM-dd";
...
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: _createFloatingActionButton(),
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
body: _createTodoList(),
);
}
Widget _createTodoList() {
// 이 부분을 _todoList를 사용하도록 변경한다.
return ListView.separated(
itemCount: _todoList.length,
itemBuilder: (BuildContext context, int index) {
return _createTodoCard(_todoList[index]);
},
separatorBuilder: (BuildContext context, int index) {
return Divider(
thickness: 8.0,
height: 8.0,
color: Colors.transparent,
);
},
);
}
Widget _createTodoCard(TodoModel todoModel) {
return Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0))),
child:
Container(padding: EdgeInsets.all(16.0), child: _createTodoItemRow(todoModel)),
);
}
Widget _createTodoItemRow(TodoModel todoModel) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
_createTodoItemContentWidget(todoModel),
Icon(Icons.keyboard_arrow_right, color: Colors.blue)
],
);
}
Widget _createTodoItemContentWidget(TodoModel todoModel) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
todoModel.getTitle(),
style: TextStyle(
fontSize: 24.0,
color: Colors.blue
)
),
Divider(
thickness: 8.0,
height: 8.0,
color: Colors.transparent,
),
Text(
DateFormat(TODO_DATE_FORMAT).format(todoModel.getCreatedTime()),
style: TextStyle(
fontSize: 18.0,
color: Colors.blueGrey
)
)
],
);
}
...
}
크게 달라진 부분은 없다. 데이터를 참조하는 방법만 변경되었다.
- _createTodoList에서 ListView의 itemCount, itemBuilder를 _todoList를 사용하는 방법으로 변경한다.
- TodoItem의 UI를 그리는 Widget들의 파라미터에 TodoModel을 전달한다.
- _createTodoCard(TodoModel todoModel), _createTodoItemRow(TodoModel todoModel) 등이 그러하다.
- TodoModel의 _createdTime을 yyyy-MM-dd 로 변경하기 위해 DateFormat을 사용한다.
- DateFormat(TODO_DATE_FORMAT).format(todoModel.getCreatedTime())
- DateFormat은 intl 패키지 안에 포함되어 있다.
현재까지의 코드는 아래 Github에 저장되어 있다.
Github : github.com/DuItDDu/Flutter-Codelabs/tree/master/Flutter-TodoList/flutter_todolist
아주 간단하게 TodoItem을 추가하고 리스트를 변경할 수 있게 되었다.
하지만, 앱을 종료하고 실행하면 모두 사라진다. 이 문제를 해결하기 위해 데이터베이스 작업이 필요하다.
그러므로, 다음 포스팅은 Flutter에 SQLite를 연동하는 작업을 진행 할 것이다.
반응형
'개발 > Flutter' 카테고리의 다른 글
Flutter - 11. TodoList App (4) TodoList에 BLoC 패턴을 적용해보자. (1) | 2021.01.27 |
---|---|
Flutter - 10. TodoList App (3) Database를 연동해보자 (SQLite, sqflite) (0) | 2021.01.26 |
Flutter - 8. TodoList App (1) 기본 UI 구성하기 (3) | 2021.01.18 |
Flutter - 7. Widget? Scaffold(AppBar, BottomNavigationBar, FloatingActionButton, Drawer) (0) | 2021.01.17 |
Flutter - 6. Widget? GridView (1) | 2021.01.13 |