seong

중복 선택 가능한 Dropdown Button 만들기 본문

Flutter/중계 플랫폼 프로젝트

중복 선택 가능한 Dropdown Button 만들기

hyeonseong 2022. 11. 29. 11:09

관심사 선택에 Dropdown Button 으로 구현할 생각이다.

pub.dev에 있는 라이브러리를 사용.

https://pub.dev/packages/dropdown_button2

의존성을 추가해 주고 시작

 

 

동작 원리 

 DropDown버튼은 선택된 상태 값으로 rebuild해서 보여주기 때문에 Stateful위젯으로 만든다.

1. 아이템을 보여줄 리스트, 선택 아이템을 담아줄 리스트를 선언

2. 버튼을 클릭

3. List 중 항목 선택

4. 선택된 항목들을 바탕으로 update를 한다.

5. update된 리스트를 rebuild를 해서 사용자에게 보여준다. 

 

전체 코드

import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "DropDownButton Test",
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  State<HomePage> createState() => _HomePage();
}

class _HomePage extends State<HomePage> {
  final List<String> items = [
    '취미1',
    '취미2',
    '취미3',
    '취미4',
  ];
  List<String> selectedItems = [];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: DropdownButtonHideUnderline(
          child: DropdownButton2(
            isExpanded: true,
            hint: Align(
              alignment: AlignmentDirectional.center,
              child: Text(
                '취미를 선택해 주세요.',
                style: TextStyle(
                  fontSize: 14,
                  color: Theme.of(context).hintColor,
                ),
              ),
            ),
            items: items.map((item) {
              // 아이템의 타입은 map 타입
              return DropdownMenuItem<String>(
                value: item,
                enabled: false,
                child: StatefulBuilder(
                  // 체크 박스의 상태 값은 stateful로 상태값을 확인
                  builder: (context, menuSetState) {
                    final _isSelected = selectedItems.contains(item);
                    return InkWell(
                      // InkWell  - 버튼화
                      onTap: () {
                        // 클릭 됬으면 리스트에 add 아니면 remote
                        _isSelected
                            ? selectedItems.remove(item)
                            : selectedItems.add(item);
                        setState(() {}); // 버튼의 상태를 rebuild
                        menuSetState(() {}); //버튼의 상태를 update
                      },
                      child: Container(
                        height: double.infinity,
                        padding: const EdgeInsets.symmetric(horizontal: 16.0),
                        child: Row(
                          children: [
                            _isSelected
                                ? const Icon(Icons.check_box_outlined)
                                : const Icon(Icons.check_box_outline_blank),
                            const SizedBox(width: 16),
                            Text(
                              item,
                              style: const TextStyle(
                                fontSize: 14,
                              ),
                            ),
                          ],
                        ),
                      ),
                    );
                  },
                ),
              );
            }).toList(),
            // 선택한 항목이 있다면 선택 항목들을 보여줌.
            value: selectedItems.isEmpty ? null : selectedItems.last,
            onChanged: (value) {},
            buttonHeight: 40,
            buttonWidth: 140,
            itemHeight: 40,
            itemPadding: EdgeInsets.zero,
            selectedItemBuilder: (context) {
              return items.map(
                (item) {
                  return Container(
                    alignment: AlignmentDirectional.center,
                    padding: const EdgeInsets.symmetric(horizontal: 16.0),
                    child: Text(
                      selectedItems.join(', '),
                      style: const TextStyle(
                        fontSize: 14,
                        overflow: TextOverflow.ellipsis,
                      ),
                      maxLines: 1,
                    ),
                  );
                },
              ).toList();
            },
          ),
        ),
      ),
    );
  }
}