ListWheelScrollView class
아이들이 바퀴를 돌려 스크롤할 수 있는 상자입니다.
이 위젯은 ListView 와 비슷 하지만, 스크롤 축을 따라 모든 자식 위젯의 크기가 동일해야 한다는 제한이 있습니다.
목록이 스크롤 오프셋 0에 있을 때 첫 번째 자식은 뷰포트 중앙에 정렬됩니다. 목록이 스크롤 오프셋 최종에 있을 때 마지막 자식은 뷰포트 중앙에 정렬됩니다.
아이들은 평면에서 스크롤하는 대신 바퀴 위에서 회전하는 것처럼 묘사됩니다.
예제 코드
알림 앱에서 특정한 시간을 정할 때, 날짜를 정할 때 흔히들 휠(Wheel) 형식으로 스크롤이 되는 다이얼로그를 사용한다.
이렇게 휠 형식으로 만들어 놓으면 기본적으로 꽤 새로운데 이는 즉 사용자로 하여금 식상함을 덜 느끼게 되는 요소라는 것이다.
놀랍게도 이 휠 다이얼로그를 아주 간단하게 바로 사용하게 만들어주는 위젯이 있는데 바로 ListWhellScrollView 위젯이다.
이 ListWheelScrollView 는 3D 캐러셀 스타일의 스크롤 가능한 리스트 위젯이다. 회전하는 바퀴 모양의 인터페이스를 제공하여, 주로 날짜 선택기나 피커(picker) 형태의 UI에서 사용되곤한다. 바로 알아보자.
하위 속성
| 속성명 | 타입 | 기본값 | 설명 |
| controller | ScrollController? | – | 현재 선택된 항목을 제어하거나 읽기 위한 컨트롤러 |
| physics | ScrollPhysics? | – | 스크롤 동작의 물리적 반응을 정의함 |
| diameterRatio | double | 2.0 | 스크롤 뷰의 원통 형태의 깊이 비율 |
| perspective | double | 0.003 | 원근 효과를 조절하는 값 |
| offAxisFraction | double | 0.0 | 스크롤 뷰를 좌우로 오프셋하는 비율 |
| useMagnifier | bool | false | 중앙 항목을 확대할지 여부 |
| magnification | double | 1.0 | 중앙 항목 확대 비율 |
| overAndUnderCenterOpacity | double | 1.0 | 중앙 위아래 항목들의 투명도 |
| itemExtent | double | – | 각 항목의 주축 크기 (필수) |
| squeeze | double | 1.0 | 항목 간 밀도 비율로 줄이면 더 많은 항목이 보임 |
| onSelectedItemChanged | ValueChanged<int>? | – | 선택된 항목이 변경될 때 호출되는 콜백 |
| renderChildrenOutsideViewport | bool | false | 뷰포트 밖의 항목을 그릴지 여부 |
| childDelegate | ListWheelChildDelegate | – | 항목을 생성할 때 사용하는 델리게이트 |
| clipBehavior | Clip | Clip.hardEdge | 뷰포트를 넘어가는 항목을 어떻게 자를지 설정 |
| hitTestBehavior | HitTestBehavior | HitTestBehavior.opaque | 히트 테스트 방식 설정 |
| restorationId | String? | – | 상태 복원을 위한 ID |
| scrollBehavior | ScrollBehavior? | – | 스크롤 동작 및 표시 스타일 정의 |
| dragStartBehavior | DragStartBehavior | DragStartBehavior.start | 사용자 드래그 시작 위치 처리 방식 |
예제 영상을 본 사람들은 알겠지만 사용하는 법은 정말 간단한데 그 이유는 바로 ListView 랑 이름만 다르지 그냥 거의 같기 때문이다.
ListWheelScrollView(
itemExtent: 45,
children: [...],
)
ListWheelScrollView 는 필수 파라미터로 itemExtent 와 children 을 받고 있다.
여기서 주목해야 할 것은 itemExtent 인데 이 파라미터가 ListView 와 차이점을 주는 이유이다. ListView 안에서는 자식들의 위젯의 크기를 직접적으로 제한해주고 있진 않다. 직접 SizedBox 로 감싸거나 ListView 안에 위젯 중 가장 큰 위젯의 크기를 따라가기 마련인데 이 ListWheelScrollView 위젯은 자식들의 높이를 지정해줘야 한다.
이제 itemExtent 에 들어간 값은 모든 자식들에게 적용되어 다 공통된 크기를 가지게 된다. 사실 위에 저 코드만 작성해도 바로 작동은 될 것이다.
하지만 보통 ListView 위젯은 이 자체만으로 많이 사용된다기보단 생성자를 넣어 builder 로 많이 사용하곤 한다. 그렇다면 이 위젯에도 있지 않겠는가?
ListWheelScrollView.useDelegate(
childDelegate: ListWheelChildBuilderDelegate(builder: (context, index) {
return Container();
},),
itemExtent: 45,
)
useDelegate 생성자를 사용해 주면 된다. 여기서 userSelegate 를 그냥 builder 라고 생각하면 바로 이해가 될 것이다. 또한 위 코드에서 알 수 있듯이 childDeleegate 라는 파라미터를 가지는데 이건 itemBuilder 라고 생각하면 된다. 근데 이제 ListWhellChildBuilerDelegate 라는 위젯을 넣어줘야 할 뿐인 것이고.
당연하겠지만 길이를 정해주는 파라미터도 존재한다.
ListWheelScrollView.useDelegate(
childDelegate: ListWheelChildBuilderDelegate(
childCount: 20,
builder: (context, index) {
return Container();
},),
itemExtent: 90,
)
이런 식으로 ListWheelChildBuilerDelegate 안에 childCount 란 값으로 길이를 지정해 줄 수 있다.
여기서 디자인을 하는 방법, 속성을 더 알아볼 수도 있겠지만 그러지 않고 다른 것에 대해 말해보겠다. 바로 '가로' 방향에 대해서다.
위의 하위 속성 표를 보면 Axis 를 조절할 수 있는 옵션이 없지 않은가? 그렇다. 이 위젯은 애초에 세로로 사용되는 것을 전제로 만든 위젯인 거다.

사실 이 위젯은 이런 time picker 같은 곳에서 사용하라고 만든 것이 맞다. 하지만 우리는 이런 걸 원하지 않을 것이다. 그래서 RotateBox 를 통해서 간단하게 가로 스크롤을 구현해 보겠다.
이런 식으로 가로 스크롤도 가능하게 만들어 줄 수 있다. 암튼 도움이 되었길 바라며 마치겠다.