본문 바로가기
App Programming/Flutter

[Flutter] Widget - ListView

by 젠틴 2022. 5. 5.

1. ListView란?

ListView Widget은 스크롤 기능이 포함된 목록 창을 제공하는 Widget입니다.

ListView Widget을 사용하기 위해선, 반드시 높이를 지정해줘야 합니다.

예를 들어, 상위 Widget(Container, SizedBox 또는 Expanded 등)에서 height를 지정해주거나 여백 영역으로 한정해줘야 합니다.

2. ListView 생성자 및 속성

https://api.flutter.dev/flutter/widgets/ListView-class.html

 

ListView class - widgets library - Dart API

A scrollable list of widgets arranged linearly. ListView is the most commonly used scrolling widget. It displays its children one after another in the scroll direction. In the cross axis, the children are required to fill the ListView. If non-null, the ite

api.flutter.dev

Flutter Material API 가이드를 통해 ListView Widget의 생성자 및 중요 속성에 대해 정리해보도록 하겠습니다.

 

○ 생성자(Constructor)

1) ListView

기본 생성자이며, 하위 Widget으로 List Widget을 사용합니다.

보유하고 있는 모든 목록을 대상으로 처리 작업을 하기 때문에, 목록이 적은 경우에 적합합니다.

<ListView 생성자>

2) ListView.builder

ListView.builder는 실제 화면에 보여지는 목록에 대해서만 처리 작업을 하기 때문에, 목록이 많은 경우에 적합합니다.

ListView.builder 생성자를 자세히 살펴보겠습니다.

<ListView.builder 생성자>

IndexedWidgetBuilder 타입의 itemBuilder라는 변수가 필수 매개변수로 정의되어 있습니다.

바로 IndexedWidgetBuilder 타입을 확인해보도록 하겠습니다.

<IndexedWidgetBuilder typedef>

IndexedWidgetBuilder 타입은 함수 타입 별칭(typedef)으로 정의되어 있습니다.

함수 타입 별칭(typedef)이란 미리 정의한 함수를 변수처럼 사용할 수 있도록 해주는 기능을 의미합니다.

IndexedWidgetBuilder typedef를 자세히 살펴보면, 매개변수로 BuildContext 타입의 context 변수와 int 타입의 index 변수를 입력 받고, Widget을 반환하도록 정의되어 있습니다.

 

여기서 context 변수와 index 변수는 사용자로부터 입력 받는 것이 아니라, 호출될 때마다 ListView.builder에서 자동으로 제공합니다.

 

3) ListView.separated

ListView.separated는 목록마다 구분선을 표시하기 때문에, 목록의 수가 정해져 있는 경우에 적합합니다. 

ListView.separated 생성자를 자세히 살펴보겠습니다.

<ListView.separated>

앞서 설명드린 IndexedWidgetBuilder 타입의 itemBuilder라는 변수와 동일 타입의 separatorBuilder라는 변수, 마지막으로 int 타입의 itemCount가 필수 매개변수로 정의되어 있습니다.

 

4) ListView.custom(별도 가이드)

 

○ 속성(Property)

1) itemExtent

<itemExtent 속성>

- 매개변수 타입 : double

- 역할 : 개별 목록의 크기 일괄 설정

 

2) children

<children 속성>

- 매개변수 타입 : List<Widget>

- 역할 : 하위 Widget 내 복수의 하위 Widget 컨텐츠 추가 가능

 

3) padding

<padding 속성>

- 매개변수 타입 : EdgeInsetsGeometry

- 역할 : ListView Widget과 하위 Widget 간의 여백

3. ListView 예제 코드 및 실행 결과

○ ListView

1) 개별 목록의 크기를 각각 지정한 경우

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.grey,
        appBar: AppBar(
          backgroundColor: Colors.teal,
          title: const Text(
            'TITLE',
          ),
        ),
        body: SafeArea(
          child: SizedBox(
            height: double.infinity,
            width: double.infinity,
            child: Column(
              children: [
                Container(
                  height: 100.0,
                ),
                Expanded(
                  child: ListView(
                    padding: const EdgeInsets.all(8),
                    children: <Widget>[
                      Container(
                        height: 30.0,
                        color: Colors.red,
                        child: const Center(
                          child: Text('Red'),
                        ),
                      ),
                      Container(
                        height: 60.0,
                        color: Colors.green,
                        child: const Center(
                          child: Text('Green'),
                        ),
                      ),
                      Container(
                        height: 90.0,
                        color: Colors.blue,
                        child: const Center(
                          child: Text('Blue'),
                        ),
                      ),
                    ],
                  ),
                ),
                Container(
                  height: 100.0,
                ),
              ],
            ),
          ),
        ),
      ),
    ),
  );
}

예제 코드의 의미는 다음과 같습니다.

  • Scaffold Widget으로 메인 화면을 구현
    • 배경 색상을 회색으로 설정
    • AppBar Widget으로 상단 메뉴 구현
      • 메뉴 색상을 암청색(teal)으로 설정
      • Text Widget으로 'TITLE'이란 제목 표시
    • SafeArea Widget으로 여백이 확보된 컨텐츠 영역 지정
      • SizedBox Widget으로 하위 Widget 영역 마련
        • SizedBox Widget의 크기를 높이, 너비 기준으로 전체 영역의 크기만큼 설정
        • child 속성으로 Column Widget을 하위 Widget으로 설정
          • children 속성으로 다수의 하위 Widget들을 세로로 배열
            • 높이 100인 Container Widget 생성
            • Expanded Widget 생성
              • ListView Widget 생성
                • 상하좌우 8 크기만큼 내부 여백 추가
                • children 속성으로 다수의 하위 Widget들을 배열
                  • 높이 30인 빨간 배경색의 Red 문자를 표시하는 Container 생성
                  • 높이 60인 초록 배경색의 Green 문자를 표시하는 Container 생성
                  • 높이 90인 파란 배경색의 Blue 문자를 표시하는 Container 생성
            • 높이 100인 Container Widget 생성

<실행 결과>
<상세 설명>

처음 설명드린대로 ListView Widget은 크기를 지정해줘야 합니다.

예제 코드에선 ListView Widget의 상위 Widget인 SizedBox Widget의 높이와 너비를 전체(double.infinity)로 설정했습니다. 이를 통해 ListView Widget이 속한 영역의 크기가 한정되었기 때문에 오류가 발생하지 않습니다.

 

2) 개별 목록의 크기를 일괄 지정한 경우

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.grey,
        appBar: AppBar(
          backgroundColor: Colors.teal,
          title: const Text(
            'TITLE',
          ),
        ),
        body: SafeArea(
          child: SizedBox(
            height: double.infinity,
            width: double.infinity,
            child: Column(
              children: [
                Container(
                  height: 100.0,
                ),
                Expanded(
                  child: ListView(
                    itemExtent: 150.0,
                    padding: const EdgeInsets.all(8),
                    children: <Widget>[
                      Container(
                        height: 30.0,
                        color: Colors.red,
                        child: const Center(
                          child: Text('Red'),
                        ),
                      ),
                      Container(
                        height: 60.0,
                        color: Colors.green,
                        child: const Center(
                          child: Text('Green'),
                        ),
                      ),
                      Container(
                        height: 90.0,
                        color: Colors.blue,
                        child: const Center(
                          child: Text('Blue'),
                        ),
                      ),
                    ],
                  ),
                ),
                Container(
                  height: 100.0,
                ),
              ],
            ),
          ),
        ),
      ),
    ),
  );
}

예제 코드의 의미는 다음과 같습니다.

  • Scaffold Widget으로 메인 화면을 구현
    • 배경 색상을 회색으로 설정
    • AppBar Widget으로 상단 메뉴 구현
      • 메뉴 색상을 암청색(teal)으로 설정
      • Text Widget으로 'TITLE'이란 제목 표시
    • SafeArea Widget으로 여백이 확보된 컨텐츠 영역 지정
      • SizedBox Widget으로 하위 Widget 영역 마련
        • SizedBox Widget의 크기를 높이, 너비 기준으로 전체 영역의 크기만큼 설정
        • child 속성으로 Column Widget을 하위 Widget으로 설정
          • children 속성으로 다수의 하위 Widget들을 세로로 배열
            • 높이 100인 Container Widget 생성
            • Expanded Widget 생성
              • ListView Widget 생성
                • 개별 목록의 크기를 150으로 일괄 지정
                • 상하좌우 8 크기만큼 내부 여백 추가
                • children 속성으로 다수의 하위 Widget들을 배열
                  • 높이 30인 빨간 배경색의 Red 문자를 표시하는 Container 생성
                  • 높이 60인 초록 배경색의 Green 문자를 표시하는 Container 생성
                  • 높이 90인 파란 배경색의 Blue 문자를 표시하는 Container 생성
            • 높이 100인 Container Widget 생성

<실행 결과>
<상세 설명>

위의 예제와 동일하게 개별 목록의 크기를 각각 지정했음에도 불구하고, 개별 목록의 크기가 150.0으로 일괄 지정되었습니다. 이유는 바로 itemExtent 속성의 값을 150.0으로 지정해주었기 때문입니다. itemExtent는 ListView Widget의 하위 Widget 크기들을 설정한 값대로 동일하게 맞춰주는 기능을 합니다.

 

○ ListView.builder

import 'package:flutter/material.dart';

void main() {
  final List<String> countries = <String>[
    '가나',
    '가봉',
    '가이아나',
    '감비아',
    '과테말라',
    '그레나다',
    '그리스',
    '기니',
    '기니비사우',
  ];

  runApp(
    MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.grey,
        appBar: AppBar(
          backgroundColor: Colors.teal,
          title: const Text(
            'TITLE',
          ),
        ),
        body: SafeArea(
          child: SizedBox(
            height: double.infinity,
            width: double.infinity,
            child: Column(
              children: [
                Container(
                  height: 100.0,
                ),
                Expanded(
                  child: ListView.builder(
                    padding: const EdgeInsets.all(8),
                    itemCount: countries.length,
                    itemBuilder: (BuildContext context, int index) {
                      return Container(
                        height: 50,
                        color: Colors.blue[100 * (index + 1)],
                        child: Center(
                          child: Text(countries[index]),
                        ),
                      );
                    },
                  ),
                ),
                Container(
                  height: 100.0,
                ),
              ],
            ),
          ),
        ),
      ),
    ),
  );
}

예제 코드의 의미는 다음과 같습니다.

  • Scaffold Widget으로 메인 화면을 구현
    • 배경 색상을 회색으로 설정
    • AppBar Widget으로 상단 메뉴 구현
      • 메뉴 색상을 암청색(teal)으로 설정
      • Text Widget으로 'TITLE'이란 제목 표시
    • SafeArea Widget으로 여백이 확보된 컨텐츠 영역 지정
      • SizedBox Widget으로 하위 Widget 영역 마련
        • SizedBox Widget의 크기를 높이, 너비 기준으로 전체 영역의 크기만큼 설정
        • child 속성으로 Column Widget을 하위 Widget으로 설정
          • children 속성으로 다수의 하위 Widget들을 세로로 배열
            • 높이 100인 Container Widget 생성
            • Expanded Widget 생성
              • ListView.builder 생성
                • 상하좌우 8 크기만큼 내부 여백 추가
                • countries 변수의 배열 데이터 수를 생성하려는 목록의 수로 설정
                • countries 변수에 있는 각 나라의 이름과 파란색 그라데이션 색상을 갖는 높이가 50인 Container 형태의 목록 생성
            • 높이 100인 Container Widget 생성
      •  

<실행 결과>

 ListView.separated

import 'package:flutter/material.dart';

void main() {
  final List<String> countries = <String>[
    '가나',
    '가봉',
    '가이아나',
    '감비아',
    '과테말라',
    '그레나다',
    '그리스',
    '기니',
    '기니비사우',
  ];

  runApp(
    MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.grey,
        appBar: AppBar(
          backgroundColor: Colors.teal,
          title: const Text(
            'TITLE',
          ),
        ),
        body: SafeArea(
          child: SizedBox(
            height: double.infinity,
            width: double.infinity,
            child: Column(
              children: [
                Container(
                  height: 100.0,
                ),
                Expanded(
                  child: ListView.separated(
                    padding: const EdgeInsets.all(8),
                    itemCount: countries.length,
                    itemBuilder: (BuildContext context, int index) {
                      return Container(
                        height: 50,
                        color: Colors.blue[100 * (index + 1)],
                        child: Center(
                          child: Text(countries[index]),
                        ),
                      );
                    },
                    separatorBuilder: (BuildContext context, int index) =>
                        const Divider(),
                  ),
                ),
                Container(
                  height: 100.0,
                ),
              ],
            ),
          ),
        ),
      ),
    ),
  );
}

예제 코드의 의미는 다음과 같습니다.

  • Scaffold Widget으로 메인 화면을 구현
    • 배경 색상을 회색으로 설정
    • AppBar Widget으로 상단 메뉴 구현
      • 메뉴 색상을 암청색(teal)으로 설정
      • Text Widget으로 'TITLE'이란 제목 표시
    • SafeArea Widget으로 여백이 확보된 컨텐츠 영역 지정
      • SizedBox Widget으로 하위 Widget 영역 마련
        • SizedBox Widget의 크기를 높이, 너비 기준으로 전체 영역의 크기만큼 설정
        • child 속성으로 Column Widget을 하위 Widget으로 설정
          • children 속성으로 다수의 하위 Widget들을 세로로 배열
            • 높이 100인 Container Widget 생성
            • Expanded Widget 생성
              • ListView.builder 생성
                • 상하좌우 8 크기만큼 내부 여백 추가
                • countries 변수의 배열 데이터 수를 생성하려는 목록의 수로 설정
                • countries 변수에 있는 각 나라의 이름과 파란색 그라데이션 색상을 갖는 높이가 50인 Container 형태의 목록 생성
                • 목록 간 구분자 표시
            • 높이 100인 Container Widget 생성

<실행 결과>

'App Programming > Flutter' 카테고리의 다른 글

[Flutter] Widget - Card  (0) 2022.05.11
[Flutter] Widget - StatefulWidget & StatelessWidget  (0) 2022.05.06
[Flutter] Widget - Expanded  (0) 2022.04.24
[Flutter] Widget - Row  (0) 2022.04.18
[Flutter] Widget - Column  (0) 2022.04.18

댓글