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

Flutter[플러터] / ListWheelScrollView 를 사용하여 리스트 뷰에 3D 효과 주기 (입체감, 원형, 바퀴, 휠, 스크롤 뷰, ListView, 실린더, 가로 스크롤) ListWheelScrollView (Flutter Widget of the Week)

by ch5c 2025. 6. 26.
반응형

ListWheelScrollView class

아이들이 바퀴를 돌려 스크롤할 수 있는 상자입니다.

이 위젯은 ListView 와 비슷 하지만, 스크롤 축을 따라 모든 자식 위젯의 크기가 동일해야 한다는 제한이 있습니다.

목록이 스크롤 오프셋 0에 있을 때 첫 번째 자식은 뷰포트 중앙에 정렬됩니다. 목록이 스크롤 오프셋 최종에 있을 때 마지막 자식은 뷰포트 중앙에 정렬됩니다.

아이들은 평면에서 스크롤하는 대신 바퀴 위에서 회전하는 것처럼 묘사됩니다.

https://youtu.be/dUhmWAz4C7Y

예제 코드

 


알림 앱에서 특정한 시간을 정할 때, 날짜를 정할 때 흔히들 휠(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 를 통해서 간단하게 가로 스크롤을 구현해 보겠다.

 

 

이런 식으로 가로 스크롤도 가능하게 만들어 줄 수 있다. 암튼 도움이 되었길 바라며 마치겠다.

 

반응형