코드코도

5. SingleChildScrollView, ListView 본문

Flutter/Concept

5. SingleChildScrollView, ListView

고도고도 고도고도 2021. 8. 18. 17:36
728x90

지난 시간에 Column에 대해 정리했었다.

오늘 정리할 내용은 Column으로 위젯들을 보여줄 때 발생할 수 있는 문제를 해결해주는 또 다른 위젯이다.

import 'package:flutter/material.dart';

void main() {
  return runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Column 예제"),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          verticalDirection: VerticalDirection.up,
          children: <Widget>[
            Container(
              height: 100,
              color: Colors.red,
            ),
            Container(
              height: 100,
              color: Colors.blue,
            ),
            Container(
              height: 100,
              color: Colors.green,
            ),
            Container(
              height: 100,
              color: Colors.black,
            ),
            Container(
              height: 100,
              color: Colors.indigo,
            ),
            Container(
              height: 100,
              color: Colors.greenAccent,
            ),
            Container(
              height: 100,
              color: Colors.white,
            ),
          ],
        ),
      ),
    );
  }
}

위의 코드를 실행하면 아래와 같은 결과가 나온다.

 

verticalDirection에 의해 아래에서 위 방향으로 Container가 적재(?) 되어 있는 것을 볼 수 있는데

맨 아래에 있는 빨간색 Contiainer가 비정상적으로 출력된다.

그 이유는 기기의 화면 크기를 벗어났기 때문이다.

빨간색 Container가 표시할 범위는 기기의 MaxHeight를 벗어난 부분이 포함되므로 저렇게 Overflow가 출력되는 것이다.

 

그렇다면 어떻게 해결할 수 있을까?

방법은 크게 SingleChildScollView와 LIstView로 두 가지가 존재한다.

SingleChildScrollView

먼저 SinglechildScrollView를 살펴보자.

SingleChildScrollView SingleChildScrollView({
	Key? key, 
	Axis scrollDirection = Axis.vertical,          
	bool reverse = false,                               
	EdgeInsetsGeometry? padding,             
	bool? primary,                             
	ScrollPhysics? physics,                           
	ScrollController? controller,                    
	Widget? child,                                
	DragStartBehavior dragStartBehavior = DragStartBehavior.start,      
	Clip clipBehavior = Clip.hardEdge,                        
	String? restorationId,                               
	ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual
    })

역시 다양한 속성들이 존재한다.

지금까지 7개 정도의 어플을 만들면서 이러한 속성들을 사용해본 적은 없다.

이 위젯의 사용용도는 위에서 말한 것처럼 스크롤을 통해 화면을 좀 더 유연하게 만들어주는 것이다.

 

Column의 부모 위젯으로 SingleChildScrollView를 추가하고

새로 빌드를 해보면 잘려서 보이지 않던 부분까지 정상적으로 출력되는 것을 볼 수 있다.

이 위젯을 이용하면 화면에 스크롤 기능이 추가되어

사용자의 입력에 따라 위-아래, 혹은 좌-우로 화면을 움직일 수 있게 된다.

ListView

LIstView 역시 해결할 수 있는 방법 중에 하나이다.

우선 위젯을 살펴보자.

ListView ListView.builder(
	Key? key,            
	Axis scrollDirection = Axis.vertical,           
	bool reverse = false,                       
	ScrollController? controller,                     
	bool? primary,                      
	ScrollPhysics? physics,                    
	bool shrinkWrap = false,                       
	EdgeInsetsGeometry? padding,                   
	double? itemExtent,                   
	required Widget Function(BuildContext, int) itemBuilder,   
	int? itemCount,                      
	bool addAutomaticKeepAlives = true,                    
	bool addRepaintBoundaries = true,                  
	bool addSemanticIndexes = true,             
	double? cacheExtent,                        
	int? semanticChildCount,                       
	DragStartBehavior dragStartBehavior = DragStartBehavior.start,      
	ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,                     
	String? restorationId,     
	Clip clipBehavior = Clip.hardEdge
    })

엄청나게 많은 속성들이 존재한다.

가장 중요한 핵심 속성은 itemBuilder와 itemCount이다.

ItemBuilder는 LIstView로 보여줄 위젯들, itemCount는 이 위젯들의 개수를 의미한다.

 

아직 이해가 안갈테니 아래의 코드를 참고해보자.

import 'package:flutter/material.dart';

void main() {
  return runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("ListView 예제"),
        ),
        body: ListView.builder(
          itemBuilder: (context, index) {
            return Container(
              height : 100,
              decoration: BoxDecoration(
                border : Border.all(
                  color : Colors.grey,
                  width: 10,
                ),
              ),
            );
          },
          itemCount: 10,
        )
      ),
    );
  }
}

itemBuilder는 인자로 context와 index를 갖는데 context는 쉽게 말해 위젯의 위치, index는 순서라고 생각하면 된다.

사실 context에 대해서도 제대로 집고 넘어가야하는데 우선 위젯의 위치라고 정의하고 다음에 추가적으로 설명하겠다.

이렇게 itemBuilder를 선언하고 itemCount에 표시할 위젯의 개수를 적어준다.

지금은 우선 10이라고 정해줬지만 리스트의 length와 같은 int형 값은 모두 가능하다.

위 코드로 빌드를 해보면 아래처럼 결과가 나온다.

 

역시 스크롤을 통해서 위-아래로 움직일 수 있다.

그렇다면 LIstVIew와 SingleChildScrollView는 차이가 없는 것인가?

얼핏보면 그렇게 생각할 수 있지만 차이는 명백하다.

ListView는 현재 화면에 보이는 위젯들만 렌더링하고 스크롤을 움직일 때 추가적으로 렌더링을 진행한다.

하지만 SingleChildScrollView는 보여질 위젯들을 모두 렌더링을 진행한다.

따라서 퍼포먼스 측면에서 차이가 많이난다.

지금은 보여질 위젯의 개수가 적지만 1000개, 10000개의 데이터를 보여준다면?

SingChildScrollView는 초기 렌더링 시간이 엄청 날 것이다. 

728x90

'Flutter > Concept' 카테고리의 다른 글

5. SingleChildScrollView, ListView  (0) 2021.08.18
4. Column, Row, Expanded  (0) 2021.08.18
3. Container, Padding  (0) 2021.08.18
2. Stateless, Stateful  (0) 2021.07.13
1. Widget  (0) 2021.07.13
0 Comments
댓글쓰기 폼