ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Flutter basic] Listview 를 사용해 원하는 UI 구현하기
    개발/flutter 2021. 7. 3. 22:08

     

    Listview 는 아주 많이 쓰이는 기능이다.

    아무 앱이나 자주 가는 사이트들을 보면 알수있듯이 리스트는 아주 흔하게 볼수있는 UI 다.

    예를 들어 게시판이나 유튜브 영상 리스트, 검색 결과 리스트 등등 이있다.

     

    리스트는 보통 서버에서 받은 데이터들을 보여주는 형식으로 자주 쓰인다. 

    따라서 갯수가 고정적이지 않고 동적으로 변하는 경우도 많이 있다.

     

    그리고 여러개일경우 핸드폰의 크기를 벗어나기 때문에 scroll 기능이 필요한경우가 있고

    리스트의 형태가 가로이거나 세로 일경우도 있다.

     

    이모든 기능들을 Listview 하나로만 구현이 가능하므로

    ListView는 매우 필수적인 기능이라 볼수있다.

     

     

    보통의 경우 서버 데이터를 보여주는 경우가 많으므로 ListView.builder() 를 사용한다.

    이거만 사용해도 회사에서 요구했던 UI들을 모두 구현(아마?) 했었다.

     

    우선은 listview를 구현 하기위해서 itemBuilder와 itemCount가 필요하다.

    itemCount는 말그대로 몇개의 리스트를 그릴건지 설정해주는것이다.

    받아온 데이터의 갯수를 여기에 넣어주면 될것이고

    itemBuilder 안에서 이 데이터를 가지고 어떻게 UI를 구성할것인지 구현하는것이다.

     

    const data = [
      "ChesPress",
      "Squat",
      "DeadLift",
      "PullUp",
      "OverHeadPress",
    ]

    이렇게 5개의 텍스트 데이터가 있다.

    이것을 세로의 리스트로 구현해보려한다.

    Listview는 이렇게 사용하면된다.

    body: ListView.builder(
            itemCount: data.length,
            itemBuilder: (BuildContext context , int index){
              return Container();
            },
          )

     

    단지 비어있는 Container 만 그렸기 때문에 아무것도 안보일것이다.

    이제 이 container안에 text를 그릴것인데

    data에 있는 데이터 순차적으로 그리기 위해서 data의 첫번쨰~ 5번쨰에 접근해야한다.

    이것을 가능하게 하는데 itemBuilder에서 제공하는 index이다.

    body: ListView.builder(
              itemCount: data.length,
              itemBuilder: (BuildContext context, int index) {
                return Container(
                  height: 100,
                  child: Text(data[index]),
                );
              },
            ),

     

    const data = [
      "ChesPress",
      "Squat",
      "DeadLift",
      "PullUp",
      "OverHeadPress",
      "Row",
      "LegPress",
      "PushUp",
      "ShoulderPress",
      "LateralRaise"
    ];
    

     

    개발자 이직 비법 보러가기

     

    이렇게 데이터의 길이만 증가되면 자동으로 리스트가 길어지면서

    Scroll 기능이 들어간다.

     

     

    Listview를 그릴때 주의해야 할 점이 있다.

    세로 Listview 라면 listview의 높이는 자식들의 크기의 합산으로 지정된다.

    위의 예라면 1개 container 의 높이는 100 이고 데이터가 10개 이므로 높이 1000이 계산이 된다.

     

    그러나 자식의 높이를 알수 없다면? 문제가 된다.

     

    한가지 예로 Expanded를 사용한 경우인데.

    Expanded 는 부모 view의 크기중 가능한 가장 큰 사이즈를 차지 한다.

     body: Container(
              height: 100,
              color: Colors.red,
              child: Expanded(
                child: Container(
                  color: Colors.blue,
                ),
              ),
            )

     

    부모인 빨간 컨테이너를 Expanded를 사용해 파란 컨테이너가 모두 덮어버릴 수 있다.

     

    이런 Expanded처럼 자식 view가 가능한 가장 큰 높이를 차지한다면? 

     body: ListView.builder(
            itemCount: data.length,
            itemBuilder: (BuildContext context, int index) {
              return Expanded(
                child: Container(
                  height: 100,
                  child: Text(data[index]),
                ),
              );
            },
          ),
    ════════ Exception caught by widgets library ═══════════════════════════════════
    The following assertion was thrown while applying parent data.:
    Incorrect use of ParentDataWidget.
    
    The ParentDataWidget Expanded(flex: 1) wants to apply ParentData of type FlexParentData to a RenderObject, which has been set up to accept ParentData of incompatible type ParentData.
    
    Usually, this means that the Expanded widget has the wrong ancestor RenderObjectWidget. Typically, Expanded widgets are placed directly inside Flex widgets.
    The offending Expanded is currently placed inside a RepaintBoundary widget.
    
    The ownership chain for the RenderObject that received the incompatible parent data was:
      ConstrainedBox ← Container ← Expanded ← RepaintBoundary ← IndexedSemantics ← NotificationListener<KeepAliveNotification> ← KeepAlive ← AutomaticKeepAlive ← KeyedSubtree ← SliverList ← ⋯
    When the exception was thrown, this was the stack
    #0      RenderObjectElement._updateParentData.<anonymous closure>
    package:flutter/…/widgets/framework.dart:5723
    #1      RenderObjectElement._updateParentData
    package:flutter/…/widgets/framework.dart:5739
    #2      RenderObjectElement.attachRenderObject
    package:flutter/…/widgets/framework.dart:5761
    #3      RenderObjectElement.mount
    package:flutter/…/widgets/framework.dart:5440
    #4      SingleChildRenderObjectElement.mount
    package:flutter/…/widgets/framework.dart:6082
    ...
    ════════════════════════════════════════════════════════════════════════════════
    
    ════════ Exception caught by widgets library ═══════════════════════════════════
    Incorrect use of ParentDataWidget.
    

     

    위와 같은 에러가 발생할 것이다. 

    따라서 listview를 사용할 때는 자식의 크기가 정해져 있어야 함을 주의하자.

     

    댓글

Designed by Tistory.