Flutter로 메인 화면에서 오늘 할 일 추가, 캘린더 모달에서는 선택된 날짜로 추가하기 (+메인/캘린더 할 일 추가 동작을 분리하는 방법)

2024. 12. 28. 10:00같이 공부합시다 - Flutter/Flutter로 To-Do 앱 만들기

728x90
반응형

 
안녕하세요! 스테디빌더입니다. 😁
 
이번 글에서도 역시나 문제점 해결입니다.
 
이번에는 문제가 하나가 아닌 둘ㅇ… 😱😱😱
다 좋은 경험이라 생각하며 해결해 봅시닷 !
 
오늘의 문제점은 이렇습니다.
 

  1. 메인 화면에서 할 일 추가 버튼으로 추가했을 때, 오늘 날짜가 아닌 캘린더에서 선택한 날짜로 할 일이 추가됩니다.
  2. 메인 화면에서 할 일 추가 했는데 캘린더 할 일 추가 모달이 호출되면서 모달 꼬임 현상이 발생됩니다.

 
우후후.. 정말 문제 많은 앱이네요. 😅😅😅
 
 
일단 1번 사항에 대해서 확인해 봅시다 : )
 
 



 


문제 개요

현재 앱에서는 메인 화면과 캘린더 모달에서 동일한 _showAddTodoDialog 메서드(할 일 추가 다이얼로그)를 호출하고 있습니다. 이처럼 구분없이 호출되다보니, 다음과 같은 문제가 발생한거죠.

  • 메인 화면에서 오늘 날짜로 추가되지 않는 문제: 캘린더에서 선택한 날짜가 기본값으로 사용되면서 메인 화면에서 오늘 날짜를 기준으로 추가할 수 없었습니다.

 
 
 


문제의 원인

  1. 날짜 전달 방식의 부족:
    • _showAddTodoDialog가 날짜 정보를 받지 않아 항상 동일한 기준으로 동작했습니다.
  2. 메인 화면과 캘린더 모달의 로직 구분 부족:
    • 메인 화면에서는 오늘 날짜를, 캘린더 모달에서는 선택된 날짜를 기준으로 로직을 분리해야 했지만, 동일한 로직으로 처리되고 있었습니다.

 
 
 
 


문제의 해결 아이디어

1. _showAddTodoDialog와 _addTodoItem 수정

  • 추가할 날짜를 매개변수로 전달하여 날짜별로 동작을 명확히 구분합니다.
  • 메인 화면과 캘린더 모달에서 각각 다른 날짜를 전달할 수 있도록 수정합니다.

2. 메인 화면과 캘린더 모달의 호출 방식 분리

  • 메인 화면에서는 오늘 날짜를 전달.
  • 캘린더 모달에서는 선택된 날짜를 전달.

 
 
 
 


문제 해결 방안

1. _showAddTodoDialog 수정

추가할 날짜를 매개변수 ( {required DateTime date} ) 로 받아 처리하도록 수정합니다.

void _showAddTodoDialog(BuildContext context, {required DateTime date}) {
  String newTask = "";

  showDialog(
    context: context,
    builder: (BuildContext context) {
      return AlertDialog(
        title: const Text("새로운 할 일 추가"),
        content: TextField(
          decoration: const InputDecoration(
            hintText: "할 일을 입력하세요",
          ),
          onChanged: (value) {
            newTask = value;
          },
        ),
        actions: [
          TextButton(
            onPressed: () {
              Navigator.of(context).pop(); // 다이얼로그 닫기
            },
            child: const Text("취소"),
          ),
          TextButton(
            onPressed: () {
              if (newTask.isNotEmpty) {
                _addTodoItem(newTask, date: date); // 전달받은 날짜로 추가
                Navigator.of(context).pop(); // 다이얼로그 닫기
              }
            },
            child: const Text("추가"),
          ),
        ],
      );
    },
  );
}

 
1> 매개변수 추가
_showAddTodoDialog( BuildContext context, {required DateTime date} )
 
2> 위 매개변수의 date 를 _addTodoItem (할 일 추가 메서드) 의 매개변수로 전달
_addTodoItem(newTask, date: date); // 전달받은 날짜로 추가
 
 
 
 
 


2. _addTodoItem 수정

추가할 날짜를 명시적으로 받아 저장하도록 수정합니다.

void _addTodoItem(String task, {required DateTime date}) {
  final dateKey = _normalizeDate(date); // 전달받은 날짜를 표준화

  setState(() {
    _todoList.add({
      'task': task,
      'isCompleted': false,
      'date': dateKey.toIso8601String(),
    });

    _calendarEvents[dateKey] = _calendarEvents[dateKey] ?? [];
    _calendarEvents[dateKey]!.add(task);
  });

  _saveTodoList();
  _saveCalendarEvents();
}

 
 
 
 
 


3. 메인 화면과 캘린더 모달 호출 분리

 

메인 화면에서 오늘 날짜로 추가

floatingActionButton: FloatingActionButton(
  onPressed: () {
    _showAddTodoDialog(context, date: DateTime.now()); // 오늘 날짜로 추가
  },
  child: const Icon(Icons.add),
),

 

캘린더 모달에서 선택된 날짜로 추가

Padding(
  padding: const EdgeInsets.only(top: 16.0),
  child: ElevatedButton.icon(
    icon: const Icon(Icons.add),
    label: const Text('할 일 추가'),
    onPressed: () {
      _showAddTodoDialog(context, date: _selectedDay ?? DateTime.now()); // 선택된 날짜로 추가
    },
  ),
),

 
 
 
 
 
 


문제 해결 후 결과

 

메인 화면

  • 항상 오늘 날짜로 할 일이 추가됩니다.

 

캘린더 모달

  • 선택한 날짜로 할 일이 추가됩니다.

 
 
 
 


 

결론

 
이제 메인 화면과 캘린더 모달에서 각각 원하는 날짜로 할 일을 추가할 수 있게 되었습니다. 😊
이 내용은 직접 해보면 이해가 쉬운데, 머릿속으로 정리하기는 복잡했습니다.
“이렇게 하면 되겠네!” 했다가, 머릿속이 엉망이 되었다가, 에이 찾아보자. 이렇게 된거죠. (ㅎ)
 
Flutter로 앱을 개발하면서 이렇게 로직을 분리하는 과정은 앱의 구조를 더 깔끔하게 만들고, 유지보수성을 높이는 데 큰 도움이 되는 것 같습니다.
 
 
 
 


 

광고

728x90

 
 


 
 
 
자, 이제 2번째 문제죠.
 

  1. 메인 화면에서 할 일 추가 버튼으로 추가했을 때, 오늘 날짜가 아닌 캘린더에서 선택한 날짜로 할 일이 추가됩니다. (DONE !)
  2. 메인 화면에서 할 일 추가 했는데 캘린더 할 일 추가 모달이 호출되면서 모달 꼬임 현상이 발생됩니다.

 
이번에는 메인 화면과 캘린더 모달에서 할 일을 추가하는 동작을 명확히 분리하고, 더 이상 화면이 꼬이지 않도록 수정해 봅시다.
 
 
 


문제 개요

 

현상

  • 메인 화면에서 FloatingActionButton을 눌러 오늘 날짜로 할 일을 추가했는데, 캘린더 모달로 전환되는 이상한 현상이 발생했습니다.
  • 이후 모달에서 닫기 버튼을 눌러도 반응하지 않으며 앱이 멈추는 문제가 나타났습니다.

 

기대 동작

  • 메인 화면에서 할 일을 추가하면 메인 화면에 그대로 머물러야 합니다.
  • 캘린더 모달에서 선택한 날짜로 할 일을 추가하면, 모달 상태만 갱신되어야 합니다.

 
 
 
 


 

문제의 원인

  1. _showAddTodoDialog의 후속 작업 미분리:
    • 현재 FloatingActionButton과 캘린더 모달에서 동일한 다이얼로그를 호출하고 있으며, 캘린더 모달의 후속 동작(_showTasksForSelectedDay())이 메인 화면에서도 실행됩니다. 그러니까, 캘린더 모달에서 할 일을 추가한 뒤에 할 일 목록의 모달이 새로 띄워지는데, 이 모달이 메인 화면에서까지 동작을 하는 것이 문제가 되는 것이죠.
    • 메인 화면에서는 이 동작이 필요하지 않지만 호출되면서 화면 전환이 발생되는 것입니다.
  2. Navigator 스택 관리 문제:
    • 불필요한 Navigator 호출로 인해 스택이 비정상적으로 관리되고, 모달 닫기 버튼이 더 이상 반응하지 않는 문제가 발생했습니다.

 
 
 
 


 

문제의 해결 아이디어

 

1. onTaskAdded 콜백 추가

  • onTaskAdded 콜백을 사용하여 후속 작업을 호출 위치에 따라 다르게 처리합니다.
  • 메인 화면에서는 onTaskAdded를 전달하지 않아 추가 후 아무런 작업도 실행되지 않습니다.
  • 캘린더 모달에서는 onTaskAdded를 통해 _showTasksForSelectedDay를 호출하여 상태를 갱신합니다.

 

2. 메인 화면과 캘린더 모달 호출 방식 분리

  • 메인 화면: 오늘 날짜로 할 일을 추가하고, 화면에 머무릅니다.
  • 캘린더 모달: 선택한 날짜로 할 일을 추가하고, 모달 상태를 갱신합니다.

 
 
 
 


 

문제 해결 방안

 

수정된 _showAddTodoDialog 코드

 
onTaskAdded 콜백을 추가하여 호출 위치에 따라 동작을 다르게 처리합니다.

void _showAddTodoDialog(BuildContext context, {required DateTime date, VoidCallback? onTaskAdded}) {
  String newTask = "";

  showDialog(
    context: context,
    builder: (BuildContext context) {
      return AlertDialog(
        title: const Text("새로운 할 일 추가"),
        content: TextField(
          decoration: const InputDecoration(
            hintText: "할 일을 입력하세요",
          ),
          onChanged: (value) {
            newTask = value;
          },
        ),
        actions: [
          // 취소 버튼
          TextButton(
            onPressed: () {
              Navigator.of(context).pop(); // 다이얼로그 닫기
            },
            child: const Text("취소"),
          ),
          // 추가 버튼
          TextButton(
            onPressed: () {
              if (newTask.isNotEmpty) {
                _addTodoItem(newTask, date: date); // 선택한 날짜로 추가
                Navigator.of(context).pop(); // 다이얼로그 닫기
                if (onTaskAdded != null) {
                  onTaskAdded(); // 후속 작업 실행
                }
              }
            },
            child: const Text("추가"),
          ),
        ],
      );
    },
  );
}

 
 
 
 


 

수정된 호출 방식

 

메인 화면

floatingActionButton: FloatingActionButton(
  onPressed: () {
    _showAddTodoDialog(context, date: DateTime.now()); // 오늘 날짜로 추가
  },
  child: const Icon(Icons.add),
),

 

캘린더 모달

Padding(
  padding: const EdgeInsets.only(top: 16.0),
  child: ElevatedButton.icon(
    icon: const Icon(Icons.add),
    label: const Text('할 일 추가'),
    onPressed: () {
      _showAddTodoDialog(
        context,
        date: _selectedDay ?? DateTime.now(), // 선택된 날짜로 추가
        onTaskAdded: _showTasksForSelectedDay, // 추가 후 모달 상태 갱신
      );
    },
  ),
),

 
 
 
 


 

문제 해결 후 결과

  1. 메인 화면:
    • FloatingActionButton을 눌러 오늘 날짜로 할 일을 추가해도 화면 전환이 일어나지 않고, 그대로 메인 화면에 머무릅니다.
  2. 캘린더 모달:
    • 선택된 날짜로 할 일을 추가하면, 모달이 유지되면서 상태가 정상적으로 갱신됩니다.
  3. Navigator 상태 정상화:
    • 모달 닫기 버튼이 정상적으로 동작하며, 더 이상 화면이 멈추지 않습니다.

 
 
 


 

결론

 
이제 메인 화면과 캘린더 모달에서 각각 적절한 동작을 수행할 수 있습니다.

  • 메인 화면에서는 FloatingActionButton을 통해 오늘 날짜로 간단히 할 일을 추가할 수 있어요.
  • 캘린더 모달에서는 선택한 날짜로 할 일을 추가하며, 상태가 갱신되도록 개선되었습니다.

 
Flutter로 앱을 개발하다 보면, 이런 작은 로직 분리가 앱의 구조를 더 깔끔하게 만들고, 사용자 경험(UX)을 대폭 개선할 수 있답니다!
 
오늘은 조금 길었죠?  (ㅎ)
오늘도 고생 많으셨습니다 !
 
끝 !

728x90
반응형