앱 개발 공부

플러터 학습기 (8) - 드롭다운에서 옵션 추가하고 삭제하기

polissage 2024. 3. 10. 20:06
728x90

 

2024.02.18 - [앱 개발 공부] - 플러터 학습기(7)-옵션 추가할 수 있는 드롭다운 만들기

 

플러터 학습기(7)-옵션 추가할 수 있는 드롭다운 만들기

개인 프로젝트를 하면서 chatGPT와 5시간 정도 씨름하여 선택지 추가 및 삭제를 할 수 있는 드롭다운을 만들었다. 드롭다운 + 텍스트필드에서 옵션을 입력하면 드롭다운이 열리면서 입력한 옵션을

polissage.tistory.com

데이터 입력 폼을 만들기 시작하면서 옵션을 추가·삭제할 수 있는 드롭다운을 구현하는데 시간을 굉장히 많이 썼다. 

기본 요구사항은 아래와 같았다.

 

1. 드롭다운 클릭했을때 옵션 추가하기 버튼 나오게 하기

2. 버튼 클릭하여 옵션 생성하기

3. 생성한 옵션 옆에 삭제 버튼이 나와서 클릭하면 삭제하기

 

여기까지는 비교적 쉽게 구현했지만 만들다보니 조금더 사용성을 매끄럽게 하고 싶었다.

아래와 같은 것들.

 

1. 1번 요구사항 + 옵션 추가하기 버튼이 기존에 입력된 옵션이 아닐때만 나오게 하기

2. 새로운 옵션 만들면 바로 선택되게 하기

 

이것들은 위 기본 요구사항보다 훨씬 시간이 더 오래 걸렸는데, 정작 시간이 가장 오래 걸렸던 문제는 마지막 옵션을 삭제했을때 드롭다운 보더가 사라지지 않아서 두껍게 선이 남는 거였다. 이 문제로 몇시간 동안 붙박이로 앉아 챗지피티와 씨름하기를 수일... 어제 마침내 그 문제를 해결했다!!

 

다 다루기에 내용이 너무 많으니 저번 포스팅에 이어서 드롭다운에서 옵션 추가하는 부분을 복습해보자.

 

나의 코드는 크게 DropdownExample 위젯과 커스텀 드롭다운을 디자인하는 CustomDropdown 위젯 2가지로 나누어져 있다.

DropdownExample에 앱바 및 UI 요소, 함수를 배치하고, CustomDropdown에 각종 드롭다운 설정을 넣는다.

 

저번 코드에서 드롭다운을 클릭했을때 옵션 추가하기 버튼이 항상 나오는 부분까지 만들었다.

 

이번에는 드롭다운에서 입력하는 값을 옵션으로 생성할 수 있게 CustomDropdown 위젯에 inputValue를 추가해보자.

class _CustomDropdownState extends State<CustomDropdown> {
  bool _isOpen = false;
  String _inputValue = '';

 

또한 옵션을 새로 추가할 수 있는 addNewOption함수와, 추가한 함수가 저장되는 dropdownValue를 DropdownExample 클래스에 만들었다.

class DropdownExample extends StatefulWidget {
  @override
  _DropdownExampleState createState() => _DropdownExampleState();
}

class _DropdownExampleState extends State<DropdownExample> {
  List<String> options = [];
  String? dropdownValue;
  
  // 새 옵션으로 추가된 newOption 값이 드롭다운 밸류가 된다.
   void addNewOption(String newOption) {
    setState(() {
      options.add(newOption);
      dropdownValue = newOption;
    });
  }

 

그러면 이제 새로 추가한 옵션이 dropdownValue에 나오도록 드롭다운 아이템을 수정하고, addNewOption 함수가 옵션 추가하기 버튼을 클릭할때 동작하게 해줘야겠다.

    body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          //하단에 customDropdown을 정의하고 불러온다.
          children: [
            CustomDropdown(
            // null로 되어있던 드롭다운 밸류를 dropdownValue로 변경해준다.
              value: dropdownValue,
              items: options.map<DropdownMenuItem<String>>((String value) {
                return DropdownMenuItem<String>(
                  value: value,
                  child: Text(value),
                );
              }).toList(),
              onChanged: (String? newValue) {
                setState(() {
                  // 여기서 드롭다운 옵션이 업데이트 될 수 있도록 한다.
                  dropdownValue = newValue;
                });
              },
            ),
          ],
        ),
      ),

 

먼저 드롭다운 안에 value 값을 dropdownValue로 수정해주고, 드롭다운 옵션 값을 업데이트 해주는 onchanged 콜백에도 내용을 추가해준다.

 

addNewOption 함수가 상위 위젯에 위치하고 있으므로, 하위 위젯 CustomDropdown에서 옵션 생성시 상위 위젯에 위치한 옵션 추가 함수를 받아 실행하는 콜백 함수가 필요하다. 이를 위해 addOptionCallback을 추가하고, CustomDropdown 클래스에도 변수를 추가해준다. 

 //addNewOption 함수 하단에 콜백함수를 추가했다.
 void addOptionCallback(String newOption) {
    if (newOption.isNotEmpty) {
      addNewOption(newOption);
    }
  }

 

CustomDropdown 위젯에 콜백함수 관련 변수 추가.

class CustomDropdown extends StatefulWidget {
  final String? value;
  final List<DropdownMenuItem<String>> items;
  final ValueChanged<String?>? onChanged;
  // 콜백함수 변수 추가
  final void Function(String)? addOptionCallback;
  

  CustomDropdown({
    required this.value,
    required this.items,
    required this.onChanged,
    //여기도 추가
    required this.addOptionCallback,
  });

 

이제 CustomDropdown에서 옵션 추가 콜백 함수로 옵션을 추가하는 부분과, 상위 위젯 DropdownExample 내 CustomDropdownButton 위젯에서도 추가한 옵션이 나올 수 있도록 콜백함수 필드를 추가해준다.

 

여기는 CustomDropdownButton 위젯.

          CustomDropdown(
              value: null,
              items: options.map<DropdownMenuItem<String>>((String value) {
                return DropdownMenuItem<String>(
                  value: value,
                  child: Text(value),
                );
              }).toList(),
              onChanged: (String? newValue) {
                setState(() {
                  dropdownValue = newValue;
                  // 나중에 설정한 옵션을 선택할 수 있도록 한다
                });
              },
             // addOptionCallback 추가
              addOptionCallback: addOptionCallback,
            ),

 

CustomDropdown에서 카테고리 추가 버튼 눌렀을 때 동작을 정의하는 onTap 영역에 옵션 추가 콜백 함수를 추가한다.

    if (_isOpen)
          Container(
              margin: EdgeInsets.only(top: 4),
              decoration: BoxDecoration(
              	 border: Border.all(),
                 borderRadius: BorderRadius.circular(4),
                  ),
              child: Column(
               children: [
                   ...widget.items.map((item) {
                       return ListTile(
                           title: item.child!,
                              onTap: () {
                               setState(() {
                                   widget.onChanged?.call(item.value);
                                      _isOpen = false;
                                      });
                              },
                          );
                      }).toList(),
                      ListTile(
                       title: Row(
                           children: [
                               Icon(Icons.add),
                               SizedBox(width: 8),
                               Text('카테고리 추가'),
                               ],
                             ),
                            onTap: () {
                              //옵션 생성 콜백을 호출해준다.                           
                                widget.addOptionCallback; // Call the add option callback
                              setState(() {
                                _isOpen = false;
                                  });
                            }
                          ),
                      ],
                  ),
              ),

 

여기까지 해보고 나니 막상 필드에 옵션 입력하는 부분이 누락되어 있다 ㅠ. 어떻게 했는지 보니 CustomDropdown에서 텍스트 필드를 정의하고 입력된 값을 옵션으로 만드는 컨트롤러를 정의하고 있다.

 

오늘은 일단 여기까지!

728x90