Flutter Simple TODO(할일관리) List

첫번째 수업에서는 DartFlutter를 살펴보고 ToDoList App 을 만들어보도록 할 것이다.

이 내용은 부산에서 진행된 Flutter 스터디 1주차를 정리한 내용입니다.

소스는 여기에서 받을수 있습니다.

Stateless 와 Stateful Widget

  • Stateless 는 동적으로 변하지 않는 위젯

  • Stateful 은 동적으로 변할수 있는 위젯

Stateful 구현은

  • createState

  • State 상속된 클래스 구현

모든 Widget은 build 함수를 필수

import 'package:flutter/material.dart';

void main() => runApp(new TodoApp());

class TodoApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return new MaterialApp(
     title: 'Todo List',
     home: new TodoList()
  );
}
}

class TodoList extends StatefulWidget {
 @override
 createState() => new TodoListState();
}

class TodoListState extends State<TodoList> {
 @override
 Widget build(BuildContext context) {
   return new Scaffold(
     appBar: new AppBar(
       title: new Text('Todo List')
    )
  );
}
}

이제 Stateful widget이 된 상태이다. 그럼 TODO 아이템을 추가를 해볼까 한다.

Body 부분 추가

우선 floating action button 을 추가를 해보자.

floatingActionButton: new FloatingActionButton(
       onPressed: _addTodoItem,
       tooltip: '추가',
       child: new Icon(Icons.add)
    ),
  • _addTodoItem 은 클릭시 발생되는 함수를 뜻한다.

  • child는 해당 위젯에 자식으로 들어가서 다시 아이콘을 추가를 한다.

body 에 리스트를 추가를 해보자.

body: _buildTodoList(),
  • _buildTodoList

Widget _buildToDoList() {
   return new ListView.builder(
       itemBuilder: (context, index) {
           if(index < _todoItems.length) {
               return _buildToDoItem(_todoItems[index]);
          }
      }
  );
}

자식 아이템도 추가해준다.

  Widget _buildToDoItem(String todoText) {
   return new ListTile(
     title: Text(todoText),
  );
}

이벤트 등록

그리고 floating button 을 클릭시 아이템을 추가 하기 위해선 이벤트도 등록해줘야 하는데 그건 pressed 에서 해주면 된다.

  • 버튼 클릭시 아이템이 하나씩 추가된다.

onPressed: _addTodoItem,
  _addTodoItem() {
  setState(() {
    int index = _todoItems.length;
    _todoItems.add('Item_$index');
  });
}

전체 소스

import 'package:flutter/material.dart';

void main() => runApp(new TodoApp());

class TodoApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return new MaterialApp(
       title: 'Todo List',
       home: new TodoList()
  );
}
}

class TodoList extends StatefulWidget {
 @override
 createState() => new TodoListState();
}

class TodoListState extends State<TodoList> {

 List<String> _todoItems = [];

 Widget _buildToDoList() {
   return new ListView.builder(
       itemBuilder: (context, index) {
         if(index < _todoItems.length) {
           return _buildToDoItem(_todoItems[index]);
        }
      }
  );
}

 Widget _buildToDoItem(String todoText) {
   return new ListTile(
     title: Text(todoText),
  );
}

 _addTodoItem() {
   setState(() {
     int index = _todoItems.length;
     _todoItems.add('Item_$index');
  });
}

 @override
 Widget build(BuildContext context) {
   return new Scaffold(
       appBar: new AppBar(
           title: new Text('Todo List')
      ),
       body: _buildToDoList(),
       floatingActionButton: new FloatingActionButton(
           onPressed: _addTodoItem,
           tooltip: '추가',
           child: new Icon(Icons.add)
      ),
  );
}
}

아이템 추가하는 화면 등록

이전까지는 한 화면에서 모든걸 진행했다. 이제 새로운 화면을 추가 해보자.

  1. 새로운 Screen 추가

    • 입력되는 문자열을 리턴하는 화면 생성

    import 'package:flutter/material.dart';

    class AddItemScreen extends StatelessWidget {
     @override
     Widget build(BuildContext context) {
       return Scaffold(
         appBar: AppBar(
           title: Text("할일 추가")
        ),
         body: TextField(
           autofocus: true,
           onSubmitted: (val) {
             Navigator.of(context).pop({'item': val});
          },
        )
      );
    }
    }

  2. 버튼 이벤트 함수에 라우팅 추가

    • 라우팅을 통해 이동된 후 값을 리턴받기를 원함

      onPressed: _navigatorAddItemScreen,
      _navigatorAddItemScreen() async {
         Map results = await Navigator.of(context).push(new MaterialPageRoute(
             builder: (BuildContext context) {
                 return AddItemScreen();
            },
        ));

         if(results != null && results.containsKey("item")) {
             _addTodoItem(results["item"]);
        }
      }

  1. 최종적으로 아이템을 리스트에 추가해서 화면 갱신

    _addTodoItem(String item) {
       setState(() {
      _todoItems.add(item);
    });
    }

할일 완료 처리

추가는 이전 시간까지 되는 걸 확인했다.

하지만 삭제는 어떻게 처리해야 할까?

방법은 여러가지가 있겠지만

  • 해당 리스트 항목에 버튼을 추가해서 클릭시 완료 처리한다.

리스트 아이템 마다 클릭시 이벤트를 먼저 등록

Widget _buildToDoItem(String todoText, int index) {
   return new ListTile(
       title: Text(todoText),
       onTap: () => _promptRemoveTodoItem(index),
  );
}

그런 다음 다이얼로그 띄워서 완료 할껀지 물어보자.

_promptRemoveTodoItem(int index) {
   showDialog(
       context: context,
       builder: (BuildContext context) {
         return new AlertDialog(
             title: new Text(' "${_todoItems[index]}" 완료 처리 하시겠습니까?'),
             actions: <Widget>[
               new FlatButton(
                   child: new Text('CANCEL'),
                   onPressed: () => Navigator.of(context).pop()
              ),
               new FlatButton(
                   child: new Text('완료'),
                   onPressed: () {
                     _removeTodoItem(index);
                     Navigator.of(context).pop();
                  }
              )
            ]
        );
      }
  );
}

최종적으로 state 함수를 통해서 완료를 진행

_removeTodoItem(int index) {
   setState(() => _todoItems.removeAt(index));
}

이상으로 오늘 Flutter 1주차 수업 내용 정리했습니다.

+ Recent posts