[플러터] Todo-App 만들기

ho's·2022년 9월 16일
1

🌈 간단한 Todo-list 만들기

☀️ 1. 프로젝트 생성하기

프로젝트 생성 후, home에 todoApp()을 호출한다.
todoApp은 상태값이 변하므로, Stateful 위젯을 사용한다.

StatefulWidget을 상속받는 todoApp 클래스를 생성한다.
StatefulWidget을 만들면 2가지 클래스가 생성된다.
반환값으로 Scaffold 위젯을 반환한다.

☀️ 2. Scaffold(); 위젯 작성하기

2-1 appBar 작성하기


appBar leading, title, actions 를 통해 대략적인 위치를 구성할 수 있다.

위와 같은 모양이 나타내어 진다.

이제 + 버튼을 누르면 창이 뜨게끔 만들어 보자.

2-2 IconButton을 입력하면 Dialog창 띄우기

눌렀을때 showDialog(); 를 호출한다.
context와 builder를 이용해 AlertDialog 를 리턴받는다.

actions: <Widget>[],

[]안에 알맞은 내용을 입력해야 한다.
우선 입력값을 받기 위해서 TextField 위젯을 사용한다.
그리고 TextField에서 입력한 값들을 어떤 버튼을 누르면 화면에 나타나게 해야하므로 눌렀을때 이벤트가 발생하는 ElevatedButton을 사용하자.
위와 같이 입력하면 아래와 같은 결과를 얻는다.

하지만 여기서 입력을하고 추가하기를 눌러도 아무런 일이 발생하지 않는다.
다음 과정으로 넘어가자!

3. 입력값을 저장하기

3-1 Todo 클래스 만들기

위와 같이 클래스를 만들어 주자 final을 통해 title, description 을 선언하고, Todo클래스의 생성자를 생선한다. required, String? 이 생소한 분들은 이에 대한 문법이 다트 공식문서에 있으니 찾아보자!

Todo 클래스를 만드는 이유는 TextField에서 입력받은 값들을 저장하기 위해 만든 것이다.

3-2 변수선언하기

title, description 이라는 빈문자열을 만든다. 이는 3-1에서 만든 title, description과 다른 것이다.

그리고, List(Todo클래스 형식)를 통해 추가할 todos를 만든다.

3-3 변화 감지하기

TextField에서 입력된 값들을 저장해야 하므로,

onChanged를 통해 변화된 값을 저장하자.

상태변화를 UI에 나타내고 싶으면 setState()를 이용해야 한다.
TextField에 변화된 value를 title에 담는다.
또한, ElevatedButton을 눌렀을때 setState()를 통해 todos 리스트(Todo클래스 형식을 가졌다.)에 값들을 추가해준다.

Todo클래스는 생성자를 만들때 title과 description 을 필수적으로 입력해야 한다.

☀️ 3. body부분 완성하기

현재까지 진행된 상황은

앱바에서 + 버튼을 누르면


위 같은 화면이 뜨는 것에서 끝이난다.

값을 입력받았지만 그것을 화면에 나타나게 하는 것은 처리하지 않았다.

body 부분을 완성해보자.

ListView.builder를 사용해야 한다.
itemBuilder와 itemCount를 입력해보자.

imterBuilder를 통해 2번째 인자인 index만큼 화면에 나타낸다.
return값으로는 InkWell 이 주어졌고 각각에 위젯을 담았다.
itemCount에는 todos.length 만큼 주어서 builder 한다.

4. 완성하기

위와 같은 진행 단계를 거치면 아래와 같이 출력된다.
전체 코드

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const todoApp(),
    );
  }
}

class Todo {
  final String title;
  final String description;

  Todo({required this.title, required this.description});
}

class todoApp extends StatefulWidget {
  const todoApp({Key? key}) : super(key: key);

  
  State<todoApp> createState() => _todoApp();
}

class _todoApp extends State<todoApp> {
  String title = "";
  String description = "";

  List<Todo> todos = [];

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: Image.asset("assets/avartar.jpeg", fit: BoxFit.fill),
        title: Text("todo - list"),
        actions: [
          IconButton(
              onPressed: () {
                showDialog(
                  context: context,
                  builder: (_) {
                    return AlertDialog(
                      title: const Text('나의 할일'),
                      actions: [
                        TextField(
                          onChanged: (value) {
                            setState(() {
                              title = value;
                            });
                          },
                          decoration: InputDecoration(hintText: "글 제목"),
                        ),
                        TextField(
                          onChanged: (value) {
                            setState(() {
                              description = value;
                            });
                          },
                          decoration: InputDecoration(hintText: "글 내용"),
                        ),
                        Center(
                            child: ElevatedButton(
                                onPressed: () {
                                  Navigator.of(context).pop();
                                  setState(() {
                                    todos.add(Todo(
                                        title: title,
                                        description: description));
                                  });
                                },
                                child: Text(" 추가 하기")))
                      ],
                    );
                  },
                );
              },
              icon: Icon(Icons.add))
        ],
      ),
      body: ListView.builder(
        itemBuilder: (_, index) {
          return InkWell(
            child: ListTile(
              title: Text(todos[index].title),
              subtitle: Text(todos[index].description),
            ),
          );
        },
        itemCount: todos.length,
      ),
    );
  }
}

추가적으로 ElevatedButtonNavigator.of(context).pop();을 추가했다.

profile
그래야만 한다

0개의 댓글