사용자가 새로운 아이패치를 추가하는 단계에서 사용자 정보를 입력할 때 이 위젯을 사용하게 되었다.
예를 들어 나는 아이패치의 좌우 착용 비율을 설정할 때 Slider 위젯을 사용했는데, 이 때 사용자가 슬라이더를 조정하여 값을 변경하면 슬라이더 양측에 해당 값이 바로바로 변경되게 하고 싶었다. 이렇게!
Slider(
value: currentSliderValue,
max: 100,
divisions: 10,
onChanged: ((value) {
setState(() {
currentSliderValue = value;
});
});
);
이렇게 setState 함수 안에서 변하는 값(value)를 변수 currentSliderValue에 할당해주었다. 하지만 내가 원했던 것처럼 값이 저렇게 실시간으로 변하지 않았다.
왜 그런지 찾아 보았다.
나는 새로운 아이패치를 추가하는 화면을 AlertDialog 안에서 구현했다. 그런데 Dialog 위젯은 StatelessWidget이라서 말 그대로 상태가 없는 위젯으로, 상태 변화가 필요 없는 화면을 구성할 때 사용한다. 처음 위젯을 그릴 때 한 번만 빌드되는 것이다.
그래서 콘솔에 출력해보면 변수 currentSliderValue의 값은 변하는데, 해당 화면에 보여지는 값은 변하지 않는 것이다.
이를 StatefulBuilder를 사용하여 해결할 수 있었다.
StatefulBuilder의 builder로 전달된 StateSetter 함수는 최상위 State의 setState를 재정의한다. (덮어씌운다.)
즉, StatefulBuilder에서 builder로 전달된 새로운 setState를 통해 StatefulBuilder로 감싼 부분만 재생성하게 되는 것이다.
return AlertDialog(
content: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return SingleChildScrollView(
child: ListBody(
children: [
const Text('좌우 착용 비율을 설정하세요.'),
Slider(
value: currentSliderValue,
max: 100,
divisions: 10,
onChanged: ((value) {
setState(() {
currentSliderValue = value;
});
});
);
];
);
);
});
);
);
추가: 또 다른 방법이 있다고 한다. AlertDialog 위젯 자체를 StatefulWidget으로 선언하는 것이다. 아하