seong

StatefulBuilder로 showDialog 사용하기 본문

Flutter/Flutter

StatefulBuilder로 showDialog 사용하기

hyeonseong 2023. 5. 27. 17:08

StatefulBuilder란?

- StatefulWidget 위젯에서 함께 사용되고, 특정 위젯의 상태를 업데이트한다.

StatefulWidget의 setState를 사용하지않고, StatefulBuilder가 가지고 있는 setState를 사용해 특정 부분을 다시 그리고, StateSetter  를 사용해 StatefulWidget으로 상태를 전달한다.

 

showDialog에서 사용 하는 이유

- showDialog는 새로운 위젯 트리를 생성해서 사용하기 때문에 Stateful위젯의 setState를 사용해도 실시간으로 변경이 되지 않는다, 이를 StatefulBuilder를 사용해 업데이트 한다.

 

위와 같은 Dialog창이 있지만 아래 처럼 함수로 생성이 된다.

void openDialog() async {}

 

이미지 추가를 선택하고, 이미지를 선택했을때 경로를 받아와 dialog에 다시 보여주고 싶었다.

이때 StatefulBuilder를 활용해서 위젯이 스스로 상태를 가지고 그림을 그리도록 했다.

 void openDialog() async {
    final ImagePicker _picker = ImagePicker();
    final ImageProvider? image = await showDialog<ImageProvider>(
      context: context,
      builder: (BuildContext context) {
        String imagePath = '';
        String text = '';

        return StatefulBuilder(  
          builder: (BuildContext context, StateSetter setState) {
            return AlertDialog(
              title: const Text('이미지와 텍스트 입력'),
              content: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text("이미지 경로 : ${imagePath}"),
                  TextField(
                    onChanged: (value) {
                      text = value;
                    },
                    decoration: const InputDecoration(
                      labelText: '텍스트',
                    ),
                  ),
                ],
              ),
              actions: [
                ElevatedButton(
                  onPressed: () async {
                    final XFile? imageFile =
                        await _picker.pickImage(source: ImageSource.gallery);
                    imagePath = imageFile?.path ?? '';
                    Logger().d("선택 이미지 경로 : ${imagePath}");
                    setState(() {});
                  },
                  child: const Text('이미지 추가'), // 이미지 추가 버튼
                ),
                ElevatedButton(
                  onPressed: () {
                    addContent(imagePath, text);
                    Navigator.of(context).pop();
                  },
                  child: const Text('추가'),
                ),
                TextButton(
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                  child: const Text('취소'),
                ),
              ],
            );
          },
        );
      },
    );
  }