본문 바로가기
flutter/Widget of the Week

Flutter[플러터] / ToggleButtons 를 사용하여 선택이 가능한 버튼 만들기 (토글, 옵션, select) ToggleButtons (Flutter Widget of the Week)

by ch5c 2025. 6. 19.
반응형

ToggleButtons class

토글 버튼 세트.

자식 목록은 direction 을 따라 배치됩니다. 각 버튼의 상태는 isSelected 에 의해 제어되는데, isSelected 는 버튼이 선택되었는지 선택되지 않았는지 여부를 판별하는 부울 값 목록입니다. 두 값 모두 목록의 인덱스를 기준으로 연관됩니다. isSelected 의 길이는 자식 목록의 길이와 일치해야 합니다.

이 구성 요소에는 Material 3 버전인 SegmentedButton 이 있는데 , 이는 Material 3에 대해 구성된 애플리케이션에 더 적합합니다(ThemeData.useMaterial3 참조)

https://youtu.be/kVEguaQWGAY

공식 문서 코드

 

 


앱을 구성할 때 빠질 수 없는 요소 중에 뭐가 있을까? 나는 그것들 중 하나가 바로 버튼이라고 생각한다. 스위치가 되었든 라디오 버튼이 되었든 일단 클릭할 수 있고 그로 인해서 상태가 변하는 버튼 말이다. 근데 그러한 버튼을 하나 두 개는 괜찮지만 여러 개의 버튼 중 다수 혹은 단일 버튼을 선택하게 하려면 조금 귀찮게 된다.

여기서 이러한 작업을 간단하게 만들어주는 위젯이 있는데 바로 ToggleButtons 위젯이다.

이 ToggleButtons 위젯은 여러 개의 버튼 중 다수 혹은 단일 버튼을 선택할 수 있게 해주는 위젯이다. 주로 bool 값의 리스트로 각각의 버튼이 선택되어 있는지의 대한 상태를 관리하고 다양한 상태 기반 UI 구성에 유용하게 사용된다. 바로 알아보자.

하위 속성
속성명 타입 기본값 설명
children List<Widget> 버튼으로 표시될 위젯 목록
isSelected List<bool> 각 버튼의 선택 여부를 나타내는 리스트
onPressed void Function(int)? null 버튼이 눌렸을 때 실행될 콜백 함수
mouseCursor MouseCursor? null 마우스 커서 스타일
tapTargetSize MaterialTapTargetSize? ThemeData.materialTapTargetSize 터치 영역 최소 크기 설정
textStyle TextStyle? null 버튼 내부 텍스트 스타일
constraints BoxConstraints? null 버튼의 크기 제약 조건
color Color? null 선택되지 않은 활성 버튼의 텍스트 및 아이콘 색상
selectedColor Color? null 선택된 버튼의 텍스트 및 아이콘 색상
disabledColor Color? null 비활성화된 버튼의 텍스트 및 아이콘 색상
fillColor Color? null 선택된 버튼의 배경색
focusColor Color? null 포커스된 버튼의 배경색
highlightColor Color? null 하이라이트 색상 (터치 시 효과)
hoverColor Color? null 마우스 호버 시 색상
splashColor Color? null 버튼 눌렀을 때 잉크 효과 색상
focusNodes List<FocusNode>? null 각 버튼에 대한 포커스 노드 리스트
renderBorder bool true 버튼 테두리 표시 여부
borderColor Color? null 테두리 색상 (비선택 상태)
selectedBorderColor Color? null 테두리 색상 (선택 상태)
disabledBorderColor Color? null 테두리 색상 (비활성 상태)
borderRadius BorderRadius? null 버튼 테두리의 모서리 반경
borderWidth double? 1.0 버튼 테두리의 두께
direction Axis Axis.horizontal 버튼을 배치할 방향
verticalDirection VerticalDirection VerticalDirection.down 수직 방향일 때 버튼 배치 순서

 

이 위젯을 처음 본다면 그냥 일반적인 버튼을 하나 만들어주는 위젯이라고 생각할 수 있다. 하지만 이 위젯은 그러한 범/부 같은 위젯이 아닌 한 번에 여러 개의 상태를 관리하고 만들어줄 수 있는 위젯이다.

ToggleButtons(
  children: [
    Icon(Icons.local_cafe),
    Icon(Icons.fastfood),
    Icon(Icons.cake),
  ],
)

일단 먼저 ToggleButtons 를 사용하려면 children 에 다양한 버튼에 사용할 위젯을 목록에 추가해줘야 한다.

위처럼 선언했으면 이제 버튼을 3개 만들겠다고 해준 거고 그 3개의 버튼에 들어갈 아이콘을 넣어준 것이 되는 것이다.

그다음은 selected 파라미터를 설정해줘야 한다.

List<bool> isSelected = [true, false, false];
ToggleButtons(
  isSelected: isSelected,
  children: [
    Icon(Icons.local_cafe),
    Icon(Icons.fastfood),
    Icon(Icons.cake),
  ],
)

isSelected 는 List<bool> 타입을 갖고 있는데 여기서 리스트의 인덱는 각 버튼과 매칭되게 된다.

이 isSelected 는 어떤 버튼을 선택하고 있는지의 대한 상태 관리를 해주기 때문에 굉장히 중요하다.

그리고 마지막으로 버튼을 눌렀을 때의 반응을 위하여 onPressed 파라미터를 사용하여 함수를 전달해 준다.

void onPressed(int index) {
  setState(() {
    for (int i = 0; i < isSelected.length; i++) {
      isSelected[i] = i == index;
    }
  });
}
ToggleButtons(
  onPressed: (index) => onPressed(index),
  isSelected: isSelected,
  children: [
    Icon(Icons.local_cafe),
    Icon(Icons.fastfood),
    Icon(Icons.cake),
  ],
),

위에서 처럼 for 문 안에 isSelected[i] = i == index 으로 만들어주면 단일 선택 동작을 구현 할 수 있게 된다.

 

 

이렇게 간단한 코드만으로 단일 선택 동작을 하는 버튼을 만들 수 있게 되었다.

근데 단일 선택이 아니라 다중 선택으로 구현하고 싶다면 isSelected[index] = !isSelected[index] 로 만들어주면 간단하게 된다.

근데 여기서 이제 생긴 게 마음에 안들 수 있다. 그러니 하위 속성을 통해 간단하게 디자인을 해보자.

먼저 color 와 selectedColor 로 선택되지 않은 버튼의 아이콘 색상과 선택된 버튼의 아이콘 색상을 바꿔줄 수 있다.

color: Colors.red,
selectedColor: Colors.blue,

그리고 이 배경 색은 fillColor 라는 속성으로 지정해 줄 수 있다.

fillColor: Colors.greenAccent,

또한 이 버튼의 경계, 보더도 renderBorder 값을 false 로 지정함으로써 없앨 수 있다.(난 개인적으로 이게 젤 예쁜 것 같다.)

renderBorder: false,

아니면 아예 이렇게 래디우스를 줘서 SegmentedButton 처럼 꾸며버릴 수도 있다.

borderRadius: BorderRadius.all(Radius.circular(30)),

그 밖에서 하이라이트 색상과 InWell 에 맞는 색상을 선택할 수도 있고 PC 버전에서라면 호버기능과 포커스기능도 지원해주고 있다.

이렇게 ToggledButtons 에 대해서 알아보았는데 실질적인 난이도는 엄청나게 쉬운데 반해 예제코드를 해괴망측하게 만들어놔서 처음 접했을 때 바로 튀어버린 기억이 있다. 암튼 도움이 되었길 바라며 마치겠다.

 

반응형