인문주의 사피엔스

Flutter에서 IntrinsicWidth가 필요한 경우 본문

프로그래밍/Flutter

Flutter에서 IntrinsicWidth가 필요한 경우

인문주 2022. 2. 17. 21:41
반응형

다음 그림은 임의의 너비를 갖는 두 개의 위젯을 아주 단순하게 나타낸 것입니다.

 

======

===

 

이 위젯들을 다음처럼 가로축 방향으로 가장 큰 너비에 맞춰 정렬하고, 세로축 방향으로 위아래 빈 공간 없이 배치하려면 어떻게 해야 할까요?

 

======

======

 

1. Column

Column은 다수의 위젯을 세로축 방향으로 배치할 때 사용하는 위젯입니다. 아래 그림은 Column을 이용해 빨간 위젯과 노란 위젯을 세로축 방향으로 배치한 것입니다. 검은 영역은 Column의 빈 공간에 해당됩니다.

 

 

다음은 위 그림의 소스코드입니다.

 

 

 

여기서 노란 위젯이 가로축 방향으로 가운데 정렬되고, 검은색의 Column 영역이 세로축 방향의 빈 공간을 꽉 채우는 이유는 Column의 기본값이 다음과 같이 설정되어있기 때문입니다.

 

Column(
    crossAxisAlignment: CrossAxisAlignment.center,
    mainAxisSize: MainAxisSize.max,
)

 

crossAxisAlignment: CrossAxisAlignment.center,

하위 위젯들을 가로축 방향으로 정렬하는 방식을 결정합니다. start, end, center, stretch, baseline 가운데 기본값은 center(가운데 정렬)입니다.

 

mainAxisSize: MainAxisSize.max,

Column의 세로축 방향의 크기를 결정합니다. min, max에서 기본값은 max(최대화)입니다.

 

2. Column(MainAxisSize.min)

mainAxisSize의 값을 MainAxisSize.min으로 바꾸면 아래 그림처럼 검은색으로 표시된 Column의 빈 공간이 세로축 방향으로 최소화됩니다.

 

 

다음은 위 그림의 소스코드입니다.

 

 

 

3. Column(MainAxisSize.min, CrossAxisAlignment.stretch)

crossAxisAlignment의 값을 CrossAxisAlignment.stretch로 바꾸면 아래 그림처럼 빨간 위젯과 노란 위젯의 너비가 늘어나 결과적으로 같아집니다.

 

 

다음은 위 그림의 소스코드입니다.

 

 

 

빨간 위젯과 노란 위젯의 너비가 같아지기는 했지만 이것은 원했던 결과가 아닙니다. 목표는 빨간 위젯의 원래(고유) 너비를 유지하는 것입니다. 빨간 위젯의 너비를 지키려면 IntrinsicWidth가 필요합니다.

 

4. IntrinsicWidth

Flutter 문서(https://api.flutter.dev/flutter/widgets/IntrinsicWidth-class.html)는 IntrinsicWidth를 다음과 같이 설명합니다.

 

A widget that sizes its child to the child's maximum intrinsic width.
자식 위젯의 크기를 그 자식 위젯의 최대 고유 너비로 만드는 위젯.

 

IntrinsicWidth를 앞의 결과에 적용하면 아래 그림과 같이 빨간 위젯의 고유 너비가 복구됩니다.

 

 

다음은 위 그림의 소스코드입니다.

 

 

 

요약하면 위젯들을 가로축 방향으로 가장 큰 너비에 맞춰 정렬하고, 세로축 방향으로 위아래 빈 공간 없이 배치하기 위한 방법은 Column과 함께 IntrinsicWidth를 사용하는 것입니다. 이렇게 IntrinsicWidth를 사용하는 위젯 배치 방식은 AlertDialog의 구현에도 적용되어 있습니다.

 

AlertDialog

AlertDialog의 build 함수에는 다음과 같은 코드가 있습니다.

 

Widget dialogChild = IntrinsicWidth(
  child: Column(
    mainAxisSize: MainAxisSize.min,
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: columnChildren,
  ),
);

 

 

children: columnChildren 

List<Widget> 형태의 위젯입니다. AlertDialog의 구성요소인 title, content, actions가 리스트에 포함됩니다.

 

crossAxisAlignment: CrossAxisAlignment.stretch,

title, content, actions를 가로축 방향으로 정렬하는 방식을 결정합니다. 여기서는 start, end, center, stretch, baseline 가운데 stretch(너비를 늘여서 정렬하기)로 설정되었습니다.

 

mainAxisSize: MainAxisSize.min,

Column의 세로축 방향의 크기를 설정합니다. 여기서는 MainAxisSize.min을 사용해 크기를 최소화하고 있습니다.

 

이와 같이 설정된 Column을 IntrinsicWidth로 감싸면 title, content, actions 가운데 고유 너비가 가장 큰 것에 맞추어 세로축 방향으로 빈 공간 없이 정렬이 됩니다.

 

5. GridView

그런데 노란 위젯을 ListView, GridView, CustomScrollView처럼 스크롤 기능을 가진 위젯으로 대체하면 결과가 이상해집니다. 아래 그림처럼 화면에 아무 것도 나타나지 않습니다.

 

 

대신 디버그 창에 다음과 같은 오류 메시지가 출력됩니다.

 

 

오류 메시지의 의미는 ListView나 GridView의 고유 크기를 계산할 수 없다는 것입니다. 왜냐하면 ListView나 GridView는 필요한 시점이 될 때까지 하위 위젯의 생성을 지연(lazy)하기 때문입니다. 다시 말해 하위 위젯들의 고유 크기를 미리 계산할 방법이 없습니다. 다음은 위 결과의 소스코드입니다.

 

 

6. GridView without IntrinsicWidth

ListView나 GridView의 크기를 지정할 필요가 없다면 IntrinsicWidth를 아예 제거해버릴 수도 있습니다. IntrinsicWidth을 제거하면 다음 그림처럼 ListView나 GridView가 빈 공간을 가득 채우게 됩니다.

 

 

다음은 위 결과의 소스코드입니다.

 

 

 

7. GridView in SizedBox in IntrinsicWidth

IntrinsicWidth의 효과를 유지하면서 GridView를 사용하려면 SizedBox를 사용해야 됩니다. 다음 그림은 SizedBox로 크기를 지정한 경우의 결과입니다.

 

 

다음은 위 결과의 소스코드입니다.

 

 

 

다음은 전체 소스코드입니다.

 

 

반응형
Comments