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

Flutter[플러터] / AnimatedList 를 사용하여 아이템 삽입/제거 할 때 커스텀 애니메이션 적용하기(애니메이티드 리스트, item, custom, remove, insert, 애니메이션, 스크롤, scroll) AnimatedList (Flutter Widget of the Week)

by ch5c 2025. 5. 20.
반응형

AnimatedList class

항목을 삽입하거나 제거할 때 해당 항목에 애니메이션을 적용하는 스크롤 컨테이너입니다.

이 위젯의 ​​AnimatedListState를 사용하여 항목을 동적으로 삽입하거나 제거할 수 있습니다. AnimatedListState 를 참조하려면 GlobalKey를 제공 하거나 항목의 입력 콜백에서 정적 메서드 of 를 사용하세요.

이 위젯은 ListView.builder 로 만든 위젯과 비슷합니다.

https://youtu.be/ZtfItHwFlZ8

공식 문서 코드

 


AnimatedList 는 리스트를 애니메이션과 함께 보여줄 수 있게 해주는 위젯이다. ListView 같은 위젯은 항목(아이템)을 추가하거나 제거할 때 애니메이션을 적용하지 않지만 이 위젯을 사용하면 넣고 싶은 애니메이션을 넣어줄 수 있다.

기본적으로 리스트 답게 itemBuilder 를 가지고 있는데 빌더 함수에 애니메이션이 들어가 있다.

또한 GlobalKey<AnimatedListState> 를 통하여 리스트에 항목을 삽입하거나 제거하는 것에 애니메이션을 넣어줄 수도 있다.

한번 간단하게 알아보자.

하위 속성
속성명 타입 기본값 설명
itemBuilder AnimatedItemBuilder 애니메이션과 함께 각 항목을 생성하는 함수
initialItemCount int 0 초기 리스트에 표시할 항목의 개수
scrollDirection Axis Axis.vertical 리스트의 스크롤 방향 (수직 또는 수평)
reverse bool false 리스트를 역방향으로 표시할지 여부
controller ScrollController? null 스크롤 위치를 제어하기 위한 컨트롤러
primary bool? null 기본(primary) 스크롤 보기로 설정할지 여부
physics ScrollPhysics? null 스크롤 동작 방식 설정
shrinkWrap bool false 자식의 크기만큼만 리스트 크기를 설정할지 여부
padding EdgeInsetsGeometry? null 리스트 안쪽 여백 설정
clipBehavior Clip Clip.hardEdge 자식이 부모 위젯을 넘어갈 때 처리 방식

 

공식 문서 코드

 

 

일단 당연하게도 리스트이기때문에 itemBuilder 를 받아야 한다.

itemBuilder: (context, index, animation) {

빌더를 만들면 이런 빌더함수가 나올텐데 주목해야 할것은 animation 이 되겠다. 이걸 사용해서 아래에 애니메이션이 들어갈자리에 그냥 톡하고 넣어주면 되는 아주 쉬운 인자값이다.

 

그다음 가장 중요한것은 당연하게도 key 일텐데 여기에다간 글로벌키를 만들고 넣어주면 되겠다. 간단하게 이렇게 만들어보자.

final GlobalKey<AnimatedListState> _listKey = GlobalKey();

이러면 key 만드는 것도 끝났다.

key: _listKey,

 

그럼 이제 이 위젯을 사용하는 주 목적인 추가/제거 시 애니메이션을 넣는 방법은 무엇일까? 방금 만든 key, 글로벌 키를 사용하면 되겠다.

가벼운 사용법을 봐보자.

final List<String> _items = ['Item 1', 'Item 2', 'Item 3'];

void _addItem() {
  final newItem = 'Item ${_items.length + 1}';
  _items.insert(0, newItem); // insert
  _listKey.currentState!.insertItem(0);
}

void _removeItem(int index) {
  final removedItem = _items.removeAt(index); // remove
  _listKey.currentState!.removeItem(
    index,
        (context, animation) => SizeTransition(
      sizeFactor: animation,
      child: ListTile(title: Text(removedItem)),
    ),
  );
}

 

먼저 리스트 하나를 초기값을 설정해주고 만들어준다. (initialItemCount 용)

final List<String> _items = ['Item 1', 'Item 2', 'Item 3'];

 

그런 후 먼저 새로운 항목을 추가 하는 메서드를 하나 만들어줄 것인데 그 안에서 먼저 리스트에 추가할 새 항목을 생성해줘야 한다.

final newItem = 'Item ${_items.length + 1}'; // 리스트에 추가될 새 항목 생성

그 후 리스트에 새항목을 삽입해주는 동작을 만들어주고 AnimatedListState 을 사용하여 애니메이션을 넣어주면 되겠다.

_items.insert(0, newItem); // 새 항목을 리스트의 맨 앞(0번째 인덱스)에 삽입
_listKey.currentState!.insertItem(0); // 애니메이션과 함께 항목 삽입

이러면 추가하는 메서드는 끝났다. 이제 제거하는 동작도 비슷하게 만들어주면 되겠다.

제거하는 동작은 리스트의 인덱스가 필요하기 때문에 인자값으로 index 를 받아주어야 한다. 설명은 귀찮으니 주석으로 대신하겠다

// AnimatedList에서 항목을 제거하는 메서드
  void _removeItem(int index) {
    // 제거될 항목을 리스트에서 꺼내고 변수에 저장 (애니메이션 빌더에서 사용됨)
    final removedItem = _items.removeAt(index);

    // AnimatedListState를 통해 애니메이션과 함께 항목 제거
    _listKey.currentState!.removeItem(
      index, // 제거할 항목의 인덱스
          (context, animation) => SizeTransition( // 애니메이션 빌더: 제거 애니메이션 정의
        sizeFactor: animation, // 애니메이션 효과로 크기 변화 적용
        child: ListTile(title: Text(removedItem)), // 제거될 항목의 위젯
      ),
    );
  }

 

이렇게 하여 메서드는 다 만들었다. 그럼 이제 본 코드에서는

AnimatedList(
  key: _listKey,
  initialItemCount: _items.length,

key 만들어둔 GlobalKey 를 넣어주고 initialItemCount 에는 가장 먼저 만들어둔 List 를 넣어주면 되겠다.

빌더 함수안에서는 SizeTrasition 을 사용하여 애니메이션을 주었다.

itemBuilder: (context, index, animation) {
  return SizeTransition(
    sizeFactor: animation,
    child: ListTile(
      title: Text(_items[index]),

 

그리고 만들어둔 메서드들은 어떻게 사용하든지 마음대로 하면 될것이다.

ElevatedButton(onPressed: _addItem, child: Text('Add Item')),

 

이렇게 AnimatedList 에 대해 알아보았다. 막 엄청 어려운 개념을 담은 위젯도 아니고 사용법이 괴랄한것도 아닌데 이거 예제 영상 길이가 젤 괴랄한것 같다. 보통 1분 초중반으로 영상 길이 맞추는게 모토 아니었나 의문이 드는 영상 길이 인것 같다. 암튼 도움이 되었길 바라며 마치겠다.

 

반응형