[flutter] showModalBottomSheet setState 적용 방법

dev-nam 2022. 6. 19. 18:27

showModalBottomSheet 위젯에서 setState 처리 방법

플러터에서 제공하는 showModalBottomSheet 위젯을 사용해보면 setState를 하더라도 모달 위젯 내부의 값이 바로 변경되지 않고, 모달 창을 닫았다가 열면 그제야 변경된 값이 반영된 것을 확인하실 수 있습니다. 

 

만약 모달 창이 열린 상태에서 사용자가 라디오나 체크박스로 옵션값을 변경하도록 구현하시려는데, 버튼을 눌러도 체크값이 변경되지 않는다면 안 되겠죠? 이런 문제를 해결하는 방법에 대해 알아보겠습니다.

 

StatefulBuilder 사용하기

showModalBottomSheet 위젯을 빌드하기 전에 StatefulBuilder 위젯으로 감싸줍니다. 그리고서 StatefulBuilder의 세터 함수 bottomState와 setState를 함께 사용하시면, 모달 창이 열린 상태에서도 값 변경이 가능해집니다.

 

참고로 bottomState만 추가하면 모달 내부의 값만 바뀌고, 부모 위젯의 값은 변경되지 않기 때문에 꼭 bottomState, setState 함수를 모두 추가하셔야 합니다. 

 

그리고 아래 예시에서 사용한 세터 함수 bottomState 명칭은 자유롭게 변경하셔서 사용하시면 됩니다.

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);
  
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late int selectedId = 0;
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      ...,
      body: SafeArea(
        child: Center(
          child: GestureDetector(
            onTap: () {
            
              // Bottom Sheet Modal
              showModalBottomSheet(
                context: context,
                shape: const RoundedRectangleBorder(
                  borderRadius: BorderRadius.vertical(
                    top: Radius.circular(30),
                  ),
                ),
                builder: (BuildContext context) {
                  return StatefulBuilder(builder: (BuildContext context, StateSetter bottomState) {
                    // StateSetter bottomState 이름은 바꾸셔서 사용하실 수 있습니다.
                    // 예를 들어, myState, subState 같이요!
                    
                    // 모달 내부 영역
                    return Container(
                      child: ListView.builder(
                        itemCount: 5,
                        itemBuilder: (BuildContext context, int index) {
                          return GestureDetector(
                            onTap: () {
                            
                              // state 값을 변경합니다.
                              // bottomState만 적용하면 bottomSheet 값은 즉시 반영되지만 parent 값은 변경되지 않습니다.
                              // 그래서 꼭 setState()를 같이 추가해주셔야 합니다.
                              bottomState(() {
                                setState(() {
                                  selectedId = index;
                                });
                              });
                            },
                            child: Row(
                              children: [
                                Icon(
                                  index == selectedId ? Icons.radio_button_on : Icons.radio_button_off,
                                ),
                                Text('리스트 항목 $index'),
                              ],
                            ),
                          );
                        },
                      ), 
                    );
                  });
                },
              );
            },
            child: Text('모달 열기'),
          ),
        ),
      ),
    );
  }
}

 

이번에는 BottomSheetModal 내부에서 setState가 즉시 반영되도록 처리하는 방법에 대해 알아봤는데요. 다음에는 자주 사용되는 BottomSheet 디자인 코드도 올려보도록 할게요!

 

코드에 대해 궁금한 게 있으시면 댓글 남겨주시면 감사하겠습니다~😄

 

 

반응형