본문 바로가기

FLUTTER APP(플러터 앱 만들기)/커스텀 다이어리

플러터 스택 리스트 만들기

커스텀 다이어리

유저가 등록하고자 하는 수업의 반복적인 요일과 전체 수업 횟수를 선택하면, 
지정한 요일과 횟수만큼 수업 일자가 계산되어 해당 수업에 대한 전체 스케줄 날짜가 저장되고,
마지막 수업 전날 지정한 시간에 알림이 와서 해당 수업이 끝나가니 회비 수금을 잊지 않게끔 도와주는 앱​

수업별로 날짜 리스트 화면이 필요하다.

난 플러터 하다가 뭔가 필요하면 무조건 pub.dev로 달려가서, 내 입맛에 맞는 패키지 쇼핑을 시작한다.

👇 이런 패키지하나 쓰면 간단히 끝날 줄 았았다.... 그땐 그랬다....

https://pub.dev/packages/grouped_list

 

grouped_list | Flutter Package

A Flutter ListView where the list items can be grouped into sections.

pub.dev


 

사용자님께서 수업별로 날짜 리스트가 많으면 한 화면에 아래 주르륵 달려서 다음 수업 볼 때 스크롤을 많이 해야 해서 싫단다.
평소엔 날짜 리스트들이 뭉쳐 있다가, 클릭하면 리스트로 아래쪽으로 표시해 달란다. 다시 클릭하면 반대로...

 

시작.

역시 새로운 요구사항이 있으면, 일단 pub.dev로 달려갔다.

하지만 결국 비슷한 리스트 형태를 못 찾았다. 사실 아는 게 없어서 뭐라고 검색해야 할지도 몰랐다. (stack list?, group list?, pile etc...)

그래서 그냥 만들어 보기로 했다.

처음엔 너무 단순하게 생각했다.

AnimatedSwitcher(암시적 애니메이션)를 이용해서 뭉친것(Stack widget)과 리스트(ListView 또는 Column Widget)를 왔다 갔다 하게 만들었다.

그런데 이건 완전 부자연스러 웠다. 각각 리스트가 예쁘게 개별로 움직이지 않고 통째로 사라졌다 통째로 생겨서..(다들 뭔 말 인지 알겠죠?)

이왕 암시적 애니메이션을 썼으니, 끝까지 암시적 애니메이션으로 가봅시다.

결국.

Stack내에서 아래와 같이 AnimatedPositioned로 구현했다. 

AnimatedContainer(
  duration: const Duration(milliseconds: 200),
  width: double.infinity,
  height: calendar.isClickList[titleIndex]
      ? lineHeight *
          calendar.individualMap.values
              .toList()[titleIndex]
              .length
      : lineHeight,
  child: Stack(
    children: List.generate(
      calendar.individualMap.values
          .toList()[titleIndex]
          .length,
      (contentIndex) => AnimatedPositioned(
        duration:
            const Duration(milliseconds: 200),
        left: calendar.isClickList[titleIndex]
            ? 0
            : contentIndex.toDouble() * 2,
        top: calendar.isClickList[titleIndex]
            ? contentIndex.toDouble() *
                lineHeight
            : 0,
        child: Padding(
          padding: const EdgeInsets.symmetric(
              vertical: 3.0),
          child: myBox(
              calendar.individualMap.values
                      .toList()[titleIndex]
                  [contentIndex],
              calendar,
              titleIndex,
              contentIndex),
        ),
      ),
    ),
  ),
)

코드를 위에서 부터 햝아...아니 훑어본다면

우선 AnimatedContainer는 Stack의 부모로서, 위젯의 크기를 잡아주기 위해서 사용했다. 

그래서 코드를 보면 스케줄날짜들의 개수에 따라 크기가 정해진다.

핵심인 AnimatedPositioned는 left, top으로 조정,

선택 안 했을때는 left : index * 2(이건 겹쳐 진걸 표시하기 위해서) / top : 0

선택했을 때는 left : 0 / top : index * lineHeight(리스트 높이)

스택리스트

생각보다 너무 간단하고 단순하여, 작성할 내용도 없지만 어제 일도 기억이 안 나기 때문에 작성한다.

언제든지 태클은 환영입니다.