본문 바로가기
개발/Flutter

Flutter ListView

by 파란검정 2022. 4. 8.
반응형

Flutter의 List

 

ListView라고 하면 일반적으로 같은 모양을 하고 있는 Widget 아이템들의 집합으로

가로 혹은 세로로 스크롤이 가능한 오브젝트를 얘기한다. 다음 이미지 처럼 말이다. 

 

 

가장 간단하게 만드는 방법은 ListView를 선언하고 children으로 widget들을 정의 하는 것이다. 

ListView(
  children: const [
    Text('01 data', style: TextStyle(fontSize: 20),),
    Text('02 data', style: TextStyle(fontSize: 20),),
    Text('03 data', style: TextStyle(fontSize: 20),),
    Text('04 data', style: TextStyle(fontSize: 20),),
    Text('05 data', style: TextStyle(fontSize: 20),),
    Text('06 data', style: TextStyle(fontSize: 20),),
    Text('07 data', style: TextStyle(fontSize: 20),),
    Text('08 data', style: TextStyle(fontSize: 20),),
    Text('09 data', style: TextStyle(fontSize: 20),),
    Text('10 data', style: TextStyle(fontSize: 20),),
    Text('11 data', style: TextStyle(fontSize: 20),),
    Text('12 data', style: TextStyle(fontSize: 20),),
    Text('13 data', style: TextStyle(fontSize: 20),),
  ],
),

 

ListView children에 widget을 넣는 것이므로 다음과 같이도 구현이 가능하다. 

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('Sample ListView'),
    ),
    body: Column(
      children: [
        const Padding(
          padding: EdgeInsets.all(8.0),
          child: Text('I am Header'),
        ),
        Expanded(
          child: ListView(
            children: _getListeItem(),
          ),
        ),
      ],
    ),
  );
}

List<Widget> _getListeItem() {
  List<Widget> result = [];
  int i = 0;
  while (i < 100) {
    result.add(Text('${i++} 번째'));
  }
  return result;
}

 

 

 

위에서 구현한 children에 widget을 넣는 방식은 widget을 다 만든 다음에 화면에 뿌려주는 방식이다. 

ListView에 표현해야 하는 item이 적다면 위와 같이 구현하는것도 문제 없겠다. 

 

 

 

만약 표현해야 하는 widget의 갯수가 많다면 이야기는 다르다. 

 

 

아래는 ListView.builder를 이용해서 구현한 ListView이다. 

ListView.builder를 이용하면 화면에 보여줄때 widget을 생성하게 된다. 

 

예를 들면 서버의 이미지를 표현할 때

ListView.builder로 작성한 widget은 화면에 보여질때

서버에서 이미지를 불러올것이기 때문에

리스트에 들어있는 item이 많아도 화면에 문제없이 표현이 가능하다. 

 

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('Sample ListView'),
    ),
    body: ListView.builder(
      itemCount: data.length,
      itemBuilder: (context, index) {
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: Text(data[index]),
        );
      },
    ),
  );
}

 

 

 

여기에서 

Header를 넣어야 한다면

Column으로 감싸고 Header에 해당하는 widget을 하나 넣어주면 될텐데

ListView를 Column으로 감싸면 다음과 같은 오류가 발생한다. 

 

Vertical viewport was given unbounded height.

 

이는 Column으로 감싼 ListView의 크기를 알수 없어서 발생하는 문제로

ListView를 Expanded로 감싸주면 된다. (또는 SizedBox로 감싸주면 된다.) 

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('Sample ListView'),
    ),
    body: Column(
      children: [
        const Padding(
          padding: EdgeInsets.all(8.0),
          child: Text('I am Header'),
        ),
        Expanded(
          child: ListView.builder(
            itemCount: data.length,
            itemBuilder: (context, index) {
              return Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text(data[index]),
              );
            },
          ),
        ),
      ],
    ),
  );
}

 

 

 

List의 각 item별로 구분선을 준 경우

 

만약에 구분선이 필요하다면 ListView.builder 대신에 ListView.separated로 구현 하면 된다. 

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('Sample ListView'),
    ),
    body: Column(
      children: [
        const Padding(
          padding: EdgeInsets.all(8.0),
          child: Text('I am Header'),
        ),
        Expanded(
          child: ListView.separated(
              itemCount: data.length,
              itemBuilder: (context, index) {
                return Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text(data[index]),
                );
              },
              separatorBuilder: (context, index) {
                return Divider();
              }),
        ),
      ],
    ),
  );
}

 

 

 

 

 

 

 

 

 

 

아래에서 볼 수 있는 List는 TMDB를 이용해서 구성한 것이다. 

 

 

위 화면을 그려주기 한 코드는 다음과 같다. 

다음 샘플 코드를 보자  

api통신을 통해 다운로드 받은 영화정보를 이용해 화면에

리스트를 구성해 표현한 것이다. 

Widget _movieList(List<Results> data) {
  
  return ListView.builder(
  	//리스트의 크기를 정의 
    itemCount: data.length,
    
    //리스트에 표현되는 Widget
    itemBuilder: (context, index) {
      var movie = data[index];
      return Padding(
        padding: const EdgeInsets.all(8.0),
        child: Row(
          children: [
            SizedBox(
                width: 80,
                height: 120,
                child: Image.network(kBASE_IMG_PATH + movie.posterPath!)),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(movie.title!),
                  Text(movie.originalTitle!),
                  Text(movie.releaseDate!),
                ],
              ),
            )
          ],
        ),
      );
    },
    
  );
}
반응형

'개발 > Flutter' 카테고리의 다른 글

Flutter Text Widget  (0) 2022.04.18
Flutter 화면 이동  (0) 2022.04.18
Flutter http 패키지와 api 통신 하기  (0) 2022.04.07
Flutter Json to model  (0) 2022.04.07
Flutter Provider (프로바이더 with MVVM) 상태관리 패키지  (0) 2022.04.05