Study Record

[Flutter] ListView 본문

Flutter/widget_scrollView

[Flutter] ListView

초코초코초코 2023. 3. 7. 20:20
728x90

🎁 ListView

여러 개의 항목을 여러 개로 스크롤 가능하게 보여줄 수 있는 위젯이다.

 

 

😶 기본 ListView

다음과 같이 기본적으로 children 으로 여러 개의 항목을 설정할 수 있다. 이 방법은 children 의 리스트 개수가 100개면 실행과 동시에 100개가 한 번에 생성된다. 따라서 개수가 많으면 비효율적일 수 있다.

ListView(
  children: List.generate(100, (index) => Container(
      height: 100,
      child: Center(child: Text(index.toString())),
    )),
);

 

 

😶 ListView.builder

ListView.builder 를 사용하여 리스트뷰를 생성할 수 있다. itemCount 가 항목의 개수이고 itemBuilder 에서 항목을 return 값으로 정할 수 있다. itemBuilder 의 index 는 몇 번째 항목인지 알려준다. builder 를 사용하면 기본 ListView 처럼 한 번에 모든 항목들이 생성되지 않고 화면에 보이는 항목과 앞 뒤로 몇 개정도만 생성했다가 스크롤을 움직이면 그 항목을 기준으로 앞뒤로 몇 개 생성/유지하고 이전 항목은 지운다.

ListView.builder(
  itemCount: 100,
  itemBuilder: (context, index) {
    return Container(
      height: 200,
      child: Center(child: Text(index.toString()))
    );
  },
);

 

 

😶 ListView.separated

ListView.builder 와 비슷한데 separatorBuilder 를 설정해야 하는 것이 다르다. itemBuilder 로 리스트 항목을 정했다면, separatorBuilder 는 항목들 사이에 들어갈 위젯을 정한다. separated 로 생성한 ListView 는 builder 로 생성한 리스트뷰와 같이 한 번에 위젯들이 생성되지 않고 화면에 보이는 항목들을 기준으로 생성하고 유지된다.

 

 

ListView.separated(
  padding: const EdgeInsets.all(16),
  itemCount: 3,
  itemBuilder: (BuildContext context, int index) {
    return Container(
      height: 50,
      color: Colors.greenAccent,
      child: Center(child: Text('Entry $index')),
    );
  },
  separatorBuilder: (context, index) => const Divider(),
);

 

 

 

😶 Column, Row + ListView

Column(
  ...
  children: [
    ...,
    Expanded(
      child: ListView(...),
    ),
  ],
)

Column, Row 위젯의 하위 위젯(children)으로 ListView 를 사용하려면 Expanded 로 ListView 를 감싸줘야 한다. 그렇지 않으면 다음과 같은 오류가 보여질 수 있다.

 

The following assertion was thrown during performResize():
Horizontal viewport was given unbounded height.

The following assertion was thrown during performResize():
Vertical viewport was given unbounded height.

 

 

 

🎁 ListView parameter

위에서 소개한 생성 방법에서 모두 적용할 수 있는 다른 파라미터에 대해 소개하자면 다음과 같다.

 

 

😶 가로 스크롤 vs 세로 스크롤(default)

scrollDirection 인자로 세로 스크롤(Axis.vertical), 가로 스크롤(Axis.horizontal)을 정할 수 있다. 세로 스크롤일 때는 세로와 관련된 위젯(ex. Column) 가로 스크롤일때는 가로와 관련된 위젯(ex. Row)을 사용해야 한다. 기본 값은 Axis.vertical 이다.

ListView(
  scrollDirection: Axis.horizontal,
  scrollDirection: Axis.vertical,
);

 

 

😶 키보드 컨트롤

keyboardDismissBehavior 인자를 사용하면 SingleChildScrollView 에 TextField 와 같이 입력 폼이 포함될 때, 사용자가 TextField 를 클릭 시 키보드가 올라왔을 때 스크롤 시 키보드가 자동으로 내려갈지(manual) 아니면 온전히 사용자에 맡길지(스크롤 시 자동으로 키보드가 내려가지 않음, onDrag) 정할 수 있다.

ListView(
  keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.manual  
  keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag
);

 

 

😶 스크롤 모양

physics 인자를 사용하면 스크롤 모양을 설정할 수 있다.

 

인자(physics) 설명
NeverScrollableScrollPhysics 사용자가 스크롤 불가능하다.
AlwaysScrollableScrollPhysics 항상 사용자가 스크롤을 가능하게 하고 스크롤 모양은 기종 기본값을 따른다.
BouncingScrollPhysics IOS 기본 스크롤 모양으로, 튕기는 모양이다.
ClampingScrollPhysics AOS 기본 스크롤 모양이다. 
PageScrollPhysics 페이지 단위로 스크롤할 수 있다.
ListView(
  physics: AlwaysScrollableScrollPhysics(),
);

 

 

+ BouncingScrollPhysics 가 적용된 상태에서 위젯이 화면 크기보다 작을 때 스크롤 시 잘려 보일 수 있다. clipBehavior 를 Clip.none 로 하면 위젯이 잘리지 않으면서 튕기는 스크롤 모양이 된다.

ListView(
  physics: AlwaysScrollableScrollPhysics(),
  clipBehavior: Clip.none,
  ...
);

 

728x90