TodoList App ๋งŒ๋“ค๊ธฐ

2024. 3. 21. 10:31ยท Flutter
๋ชฉ์ฐจ
  1. 1. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ๊ตฌ์„ฑํ•˜๊ธฐ
  2. 2. main.dart ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ
  3. 3. Model ํด๋ž˜์Šค ์ƒ์„ฑํ•ด๋ณด๊ธฐ
  4. 4. view ๋งŒ๋“ค์–ด ๋ณด๊ธฐ
๋ฐ˜์‘ํ˜•
๐ŸšฉTodoList App ๋งŒ๋“ค๊ธฐ ๋ชฉํ‘œ
1. ํด๋” ๊ตฌ์กฐ ์žก๊ธฐ
2. main ํŒŒ์ผ ๋งŒ๋“ค์–ด ๋ณด๊ธฐ
3. Model ํด๋ž˜์Šค ์ƒ์„ฑํ•ด๋ณด๊ธฐ
4. View ๋งŒ๋“ค์–ด ๋ณด๊ธฐ
5. ViewModel ๋งŒ๋“ค์–ด ๋ณด๊ธฐ
6. view(todo_list_view.dart) ์— ๋ฐ์ดํ„ฐ ๋ถ„๋ฆฌ ํ•˜๊ธฐ

 

 

1. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ๊ตฌ์„ฑํ•˜๊ธฐ

2. main.dart ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ

import 'package:flutter/material.dart';

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

class TodoApp extends StatelessWidget {
  const TodoApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: SafeArea(
        child: Scaffold(
          appBar: AppBar(title: const Text("TodoList"),),
          body: Center(
            child: Text("My Todo"),
          ),
        ),
      ),
    );
  }
}

 

import 'package:flutter/material.dart';
import 'package:my_todo_mvvm/views/todo_list_view.dart';

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

class TodoApp extends StatelessWidget {
  const TodoApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: SafeArea(
        child: Scaffold(
          appBar: AppBar(title: const Text("TodoList"),),
          body: TodoListView(),
        ),
      ),
    );
  }
}

 

3. Model ํด๋ž˜์Šค ์ƒ์„ฑํ•ด๋ณด๊ธฐ

/models/todo_item.dart ํŒŒ์ผ ์ƒ์„ฑํ•˜๊ธฐ

// Model
class TodoItem {
  String title;
  bool isDone;

  TodoItem({required this.title, this.isDone = false});
}

 

 

4. view ๋งŒ๋“ค์–ด ๋ณด๊ธฐ

/views/todo_list_view.dart ํŒŒ์ผ ์ƒ์„ฑํ•˜๊ธฐ (1๋‹จ๊ณ„)

import 'package:flutter/material.dart';


// View ํด๋ž˜์Šค 

class TodoListView extends StatefulWidget {
  const TodoListView({super.key});

  @override
  State<TodoListView> createState() => _TodoListViewState();
} // end of TodoListView class


class _TodoListViewState extends State<TodoListView> {

  final TextEditingController _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        children: [
          TextField(
            controller: _controller,
            decoration: InputDecoration(
              hintText: 'Enter todo item...',
              suffix: IconButton(
                icon: Icon(Icons.add),
                onPressed: () {
                 setState(() {
                   // build() ๋ฉ”์„œ๋“œ ์žฌ ํ˜ธ์ถœ
                   _controller.clear();
                 });

                },
              )
            ),
          ),


        ],
      ),
    );
  }
} // end of _TodoListViewState

 

TextEditingController๋Š” TextField ์œ„์ ฏ์—์„œ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ๊ด€๋ฆฌํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด TextField์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ฐ’์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜, TextField์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜, TextField๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋“ฑ ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์ž…๋ ฅ๊ฐ’ ์ ‘๊ทผ:
    • *TextEditingController*๋Š” _controller.text ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด ํ˜„์žฌ **TextField*์— ์ž…๋ ฅ๋œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ **TextField*์— ์ž…๋ ฅํ•œ ๋‚ด์šฉ์„ ๊ฐ€์ ธ์™€์„œ ๋กœ์ง์— ํ™œ์šฉํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๊ณณ์— ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์ž…๋ ฅ๊ฐ’ ๋ณ€๊ฒฝ:
    • *_controller.text = 'newValue'*์™€ ๊ฐ™์ด **TextEditingController*์˜ text ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด **TextField*์˜ ๊ฐ’์„ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ์ž…๋ ฅ๊ฐ’ ์ดˆ๊ธฐํ™”:
    • *TextEditingController*์˜ clear ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ **TextField*์˜ ๋‚ด์šฉ์„ ์‰ฝ๊ฒŒ ์ง€์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅ์„ ์™„๋ฃŒํ•œ ํ›„ ์ž…๋ ฅ ํ•„๋“œ๋ฅผ ์ดˆ๊ธฐํ™”ํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  4. ์ž…๋ ฅ ๋ณ€๊ฒฝ ๊ฐ์ง€:
    • *TextEditingController*์— ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ **TextField*์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ž…๋ ฅ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ ํŠน์ • ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํ™”๋ฉด ๋งŒ๋“ค๊ธฐ 2๋‹จ๊ณ„

import 'package:flutter/material.dart';
import 'package:my_todo_mvvm/models/todo_item.dart';

// View ํด๋ž˜์Šค

class TodoListView extends StatefulWidget {
  const TodoListView({super.key});

  @override
  State<TodoListView> createState() => _TodoListViewState();
} // end of TodoListView class

class _TodoListViewState extends State<TodoListView> {
  final TextEditingController _controller = TextEditingController();

  // ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ ๋งŒ๋“ค์–ด ๋ณด๊ธฐ
  List<TodoItem> _todoItems = [
    TodoItem(title: 'ํ”Œ๋Ÿฌํ„ฐ ๊ณต๋ถ€ํ•˜๊ธฐ', isDone: false),
    TodoItem(title: '๋‚ฎ์ž  ์ž๊ธฐ', isDone: true),
  ];

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        children: [
          TextField(
            controller: _controller,
            decoration: InputDecoration(
              hintText: 'Enter todo item...',
              suffix: IconButton(
                icon: Icon(Icons.add),
                onPressed: () {
                  setState(() {
                    // build() ๋ฉ”์„œ๋“œ ์žฌ ํ˜ธ์ถœ
                    _controller.clear();
                  });
                },
              ),
            ),
          ),
          //
          Expanded(
            child: ListView.builder(
              itemCount: _todoItems.length,
              itemBuilder: (context, index) {
                var item = _todoItems[index];
                // ๋‘๊ฐœ์˜ ์ธ์ˆ˜ ๊ฐ’์„ ๋ฐ›์•„์„œ ์œ„์ ฏ์„ ๋ฆฌํ„ด ์‹œํ‚ค๋ฉด ๋œ๋‹ค.
                return ListTile(
                  title: Text(item.title),
                  trailing: Checkbox(
                    value: item.isDone,
                    onChanged: (value) {
                      print("value : ${value}");
                      setState(() {
                        _todoItems[index].isDone = value ?? false;
                      });
                    },
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
} // end of _TodoListViewState

 

ViewModel ๋งŒ๋“ค๊ธฐ

 

// ViewModel
import 'package:my_todo_mvvm/models/todo_item.dart';

class TodoListViewModel {

  // ํ™”๋ฉด ์‚ฌ์šฉ๋  ๋ฐ์ดํ„ฐ
  List<TodoItem> _items = []; // private

  // get ๋ฉ”์„œ๋“œ ๋งŒ๋“ค์–ด ์ฃผ๊ธฐ
  List<TodoItem> get items => _items;

  // ๋ฆฌ์ŠคํŠธ์— TodoItem ๊ฐ์ฒด๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์„œ๋“œ ๋งŒ๋“ค๊ธฐ
  void addItem(String title) {
    _items.add(TodoItem(title: title, isDone: false));
  }

  void toggleItem(TodoItem todo) {
    todo.isDone = !todo.isDone;
  }

}

 

todo_list_view.dart ์ˆ˜์ •

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:my_todo_mvvm/models/todo_item.dart';
import 'package:my_todo_mvvm/view_models/todo_list_view_model.dart';

// View ํด๋ž˜์Šค

class TodoListView extends StatefulWidget {
  const TodoListView({super.key});

  @override
  State<TodoListView> createState() => _TodoListViewState();
} // end of class

class _TodoListViewState extends State<TodoListView> {

  final TextEditingController _controller = TextEditingController();
  final TodoListViewModel listViewModel = TodoListViewModel();





  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        children: [
          TextField(
            controller: _controller,
            decoration: InputDecoration(
              hintText: 'Enter Todo Item',
              suffix: IconButton(
                icon: Icon(Icons.add),
                onPressed: (){
                  setState(() {
                    listViewModel.addItem(_controller.text);
                    _controller.clear();
                  });
                },
              )
            ),
          ),
          //
          Expanded(
            child: ListView.builder(
              itemCount: listViewModel.items.length,
              itemBuilder: (context, index){
                var item = listViewModel.items[index];
                // ๋‘๊ฐœ ์ธ์ˆ˜๊ฐ’์„ ๋ฐ›์•„์„œ ์œ„์ ฏ์„ ๋ฆฌํ„ด
                return ListTile(
                  title: Text(item.title),
                  trailing: Checkbox(
                    value: item.isDone,
                    onChanged: (value) {
                      print('value : ${value}');
                      setState(() {
                        listViewModel.toggleItem(item);
                      });
                    },
                  ),
                );
            },),
          )

        ],
      ),
    );
  }
} // end of _TodoListViewState

 

 

๋ฐ˜์‘ํ˜•
์ €์ž‘์žํ‘œ์‹œ ๋น„์˜๋ฆฌ ๋ณ€๊ฒฝ๊ธˆ์ง€ (์ƒˆ์ฐฝ์—ด๋ฆผ)

'Flutter' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

typedef์™€ ํ•จ์ˆ˜  (0) 2024.03.30
dart ์ด๋ก   (0) 2024.03.30
Flutter MVVM ํŒจํ„ด - 1  (0) 2024.03.19
dart ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ - 3  (0) 2024.03.15
dart ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ - 2  (0) 2024.03.15
  1. 1. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ๊ตฌ์„ฑํ•˜๊ธฐ
  2. 2. main.dart ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ
  3. 3. Model ํด๋ž˜์Šค ์ƒ์„ฑํ•ด๋ณด๊ธฐ
  4. 4. view ๋งŒ๋“ค์–ด ๋ณด๊ธฐ
'Flutter' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • typedef์™€ ํ•จ์ˆ˜
  • dart ์ด๋ก 
  • Flutter MVVM ํŒจํ„ด - 1
  • dart ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ - 3
2์ฃผ๋…˜
2์ฃผ๋…˜
๊ฐ€๋””์‚ฌ๋Š” ๊ฐœ๋ฐœ์ž์˜ ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ
๋ฐ˜์‘ํ˜•
2์ฃผ๋…˜
Just Do "IT"
2์ฃผ๋…˜
์ „์ฒด
์˜ค๋Š˜
์–ด์ œ
  • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (245) N
    • ์ด๋ก  (0)
    • Node.js (2)
    • Flutter (19)
    • Project (1)
      • Team Project (3)
    • Daily (0)
      • ์ผ๊ธฐ (0)
      • ๋ฆฌ๋ทฐ (0)
    • Spring Boot (23)
      • ์Šคํ”„๋ง๋ถ€ํŠธ ์˜ˆ์ œ (20)
    • Java (88)
      • Java ์ด๋ก  (67)
      • Java ์—ฐ์Šต๋ฌธ์ œ (21)
      • ์˜ค๋ฅ˜ ๋…ธํŠธ (0)
    • HTML (9)
      • HTML ์ด๋ก  (9)
      • HTML ์‹ค์Šต (0)
    • CSS (27)
      • CSS ์ด๋ก  (19)
      • CSS ์‹ค์Šต (8)
    • JavaScript (8)
      • JS ์ด๋ก  (5)
      • JS ์‹ค์Šต (0)
      • jQuery (3)
    • React (19)
      • ์ด๋ก  (13)
      • ์‹ค์Šต (6)
    • SQL (18)
      • SQL_์ด๋ก  (18)
    • Git (3)
    • ์ž๊ฒฉ์ฆ (18) N
      • SQLD (15) N
      • ์ •๋ณด์ฒ˜๋ฆฌ๊ธฐ์‚ฌ (3)
    • ๊ธฐ์ˆ ๋ฉด์ ‘ (4)

๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

  • ํ™ˆ
  • ํƒœ๊ทธ
  • ๋ฐฉ๋ช…๋ก

๊ณต์ง€์‚ฌํ•ญ

์ธ๊ธฐ ๊ธ€

ํƒœ๊ทธ

  • ์ œ์ด์ฟผ๋ฆฌ
  • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ
  • DART
  • Java
  • springboot
  • ํ”Œ๋Ÿฌํ„ฐ
  • JPA
  • flutter ๊ธฐ์ดˆ
  • TypeScript
  • ๋Œ“๊ธ€๊ตฌํ˜„
  • SQL
  • ๋ฐฑ์•ค๋“œ
  • ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ
  • ์Šคํ”„๋ง๋ถ€ํŠธ
  • ์ž๋ฐ”
  • Flutter
  • JavaScript
  • ๋ณ€์ˆ˜
  • ํ”Œ๋Ÿฌํ„ฐ ๊ธฐ์ดˆ
  • ๋ฆฌ์•กํŠธ
  • ์ƒ์ˆ˜
  • jQuery
  • Spring
  • JSP
  • sqld
  • ๋ฒก์—”๋“œ
  • CSS
  • HTML
  • ๊ฐœ๋ฐœ์ž
  • ํ”„๋ก ํŠธ์•ค๋“œ

์ตœ๊ทผ ๊ธ€

hELLO ยท Designed By ์ •์ƒ์šฐ.v4.2.1
2์ฃผ๋…˜
TodoList App ๋งŒ๋“ค๊ธฐ
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”

๋‹จ์ถ•ํ‚ค

๋‚ด ๋ธ”๋กœ๊ทธ

๋‚ด ๋ธ”๋กœ๊ทธ - ๊ด€๋ฆฌ์ž ํ™ˆ ์ „ํ™˜
Q
Q
์ƒˆ ๊ธ€ ์“ฐ๊ธฐ
W
W

๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๊ธ€

๊ธ€ ์ˆ˜์ • (๊ถŒํ•œ ์žˆ๋Š” ๊ฒฝ์šฐ)
E
E
๋Œ“๊ธ€ ์˜์—ญ์œผ๋กœ ์ด๋™
C
C

๋ชจ๋“  ์˜์—ญ

์ด ํŽ˜์ด์ง€์˜ URL ๋ณต์‚ฌ
S
S
๋งจ ์œ„๋กœ ์ด๋™
T
T
ํ‹ฐ์Šคํ† ๋ฆฌ ํ™ˆ ์ด๋™
H
H
๋‹จ์ถ•ํ‚ค ์•ˆ๋‚ด
Shift + /
โ‡ง + /

* ๋‹จ์ถ•ํ‚ค๋Š” ํ•œ๊ธ€/์˜๋ฌธ ๋Œ€์†Œ๋ฌธ์ž๋กœ ์ด์šฉ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํ‹ฐ์Šคํ† ๋ฆฌ ๊ธฐ๋ณธ ๋„๋ฉ”์ธ์—์„œ๋งŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.