개요
특정 영역에 위젯을 배치할 때 그냥 위젯을 배치하는 것이 아니라 어느 영역을 설정한 후 위젯을 배치한다.
그럴 때 Flutter에서는 단일 위젯을 배치할 때 `Container` 위젯과 `SizedBox` 위젯을 사용하여 그 영역을 설정하곤 한다.
이번 포스트에서는 `Container` 위젯에 대해 알아볼 것이다.
Container
Container란?
`Container`의 의미는 용기, 담을 수 있는 무언가라는 의미로 정석적인 의미와 상당히 사용하는게 비슷한 위젯이다.
UI요소를 감싸고, 다양한 형태를 취할 수 있는 위젯이다.
위의 설명은 `SizedBox`와 굉장히 비슷한데, `SizedBox`와의 결정적인 차이점은 `Container`위젯은 그 자체를 꾸밀 수 있다는 것이다.
사용예시
Container()
Container 위젯은 위와 같이 사용이 가능하다.
하지만 이렇게 덩그러니 넣으면 시각적으로 아무것도 일어나지 않기에, 내부 프로퍼티를 채워줘야한다.
간단한 예시로 아래와 같이 코드를 작성하면, ▼
Container(
width: 100,
height: 100,
color: Colors.blue,
)
화면에 이렇게 파란색 사각형이 나오게 된다. ▼
Container의 프로퍼티들
앞에서 몇가지 봤지만, 이보다 더 많은 프로퍼티들을 가지고 있다. ▼
이번 포스트에서는 많이 사용되는 것들을 위주로 보자.
width, height
가장 먼저 `width`와 `height`다.
이름 뜻 그대로 너비와 높이 값을 조절할 수 있다.
아래와 같이 코드를 작성하면, ▼
Container(
width: 200,
height: 100,
color: Colors.blue,
),
이렇게 너비와 높이가 맞춰진 `Container`가 나오게 된다. ▼
Q. 그런데 width와 height는 nullable한 값인데, 안넣으면 어떻게 되는거?
A. 이는 Container의 부모, 자식 위젯에 따라 그 모양이 달라진다.
이에 대한 내용은 프로퍼티에 대한 설명이 끝나고 마저 다룰 예정이다.
color
앞의 예시에서도 봤지만, `color` 프로퍼티가 있다.
`Color` 클래스의 인스턴스를 받으며, `Colors`를 통해 미리 정의된 색상을 키워드를 통해 불러올 수 있다. ▼
Container(
width: 200,
height: 100,
color: Colors.red,
),
child
다음은 child 프로퍼티다.
Container는 하나의 자식 위젯을 child 프로퍼티를 통해서 Container 내부에 넣을 수 있다.
위젯이기만 하면 뭐든지 들어갈 수 있다.
다만 크기가 정해진 Container보다 더 크게 설정되면 오버플로우가 나게 되니 이는 주의해야한다.
아래와 같이 `Text` 위젯을 넣으면, ▼
Container(
width: 100,
height: 100,
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.red,
),
child: Text("고라니고라니"),
)
이렇게 `Container`안에 `Text`위젯이 들어가게 된다. ▼
padding
`padding` 프로퍼티는 `Container`의 `child`와의 여백을 설정하는 프로퍼티이다.
원래의 `Padding` 위젯은 위젯과 위젯간의, 즉 위젯 밖에 설정되는 여백을 설정하는데, `Container`의 `padding`은 `Container` 내부의 여백을 설정한다. ▼
`padding` 프로퍼티는 `EdgeInsetsGeometry`라는 추상 클래스를 구현한 클래스를 구현한 클래스들을 받는다.
Q. EdgeInsetsGeometry를 구현한 클래스들...?
A. EdgeInsetsGeometry 이야기를 했고, 이를 구현한 클래스가 있다고 했다.
그런데 그래봐야 이 추상 클래스를 구현한 클래스는 `EdgeInsets`와 `EdgeInsetsDirectional` 뿐인데, `EdgeInstesDirectional`은 padding을 절대적으로 넣는게 아니라 상대적으로 넣기에 우리는 `EdgeInsets`만 사용한다.
`EdgeInsets`에는 `all`, `only`, `symmetric` 등등 여러 생성자가 존재한다.
현재 포스트에서는 모두 보지는 못하기에 다음 포스트에서 자세하게 다룰 예정이다.
아래와 같이 크기가 동일한 `Container`를 `Container`안에 넣으면 겹쳐져서 빨간색이 보이지 않게 되어야하는데 `padding` 값으로 모든 방향에 10만큼의 거리를 두게끔 넣으면, ▼
Container(
width: 100,
height: 100,
padding: EdgeInsets.all(10),
color: Colors.red,
child: Container(
width: 100,
height: 100,
color: Colors.white,
)
이렇게 여백을 가진 채로 들어가게 된다. ▼
alignment
`alignment` 프로퍼티는 `Container`내부의 위젯을 어디에 정렬시킬지를 정하는 프로퍼티다.
`alignment` 프로퍼티도 `padding`과 비슷하게 `AlignmentGeometry`라는 추상 클래스를 구현한 클래스를 받는다.
Q. AlignmentGeometry를 구현한 클래스들...?
A. 앞에서 EdgeInsetsGeometry 이야기를 했고, 이를 구현한 클래스가 있다고 했다.
마찬가지로 AlignmentGeometry란게 있고, 이를 구현한 클래스도 있다.
그런데 그래봐야 이 추상 클래스를 구현한 클래스는 `Alignment`와 `AlignmentDirectional` 뿐인데, `AlignmentDirectional`은 alignment을 절대적으로 넣는게 아니라 상대적으로 넣기에 우리는 `Alignment`만 사용한다.
Alignment에는 내부에 정의된 여러 인스턴스가 있는데, `topLeft`, `topCenter`, `topRight`, `centerLeft`, `center`, `centerRight`, `bottomLeft`, `bottomCenter`, `bottomRight`가 있다.
다들 이름 그대로 동작하기 때문에 크게 어렵지 않다.
아까 예시를 받아와 아래와 같이 `alignment`를 `center`로 넣어보면,
Container(
width: 100,
height: 100,
padding: EdgeInsets.all(10),
color: Colors.red,
alignment: Alignment.center,
child: Text("고라니"),
)
이렇게 가운데 정렬이 되어있는 것을 알 수 있다. ▼
decoration (BoxDecoration)
다음은 `decoration`으로 `SizedBox`와 본격적인 차이를 보여주는 프로퍼티다.
`decoration` 프로퍼티는 `BoxDecoration` 클래스를 받으며, `BoxDecoration` 클래스는 다음과 같이 무수히 많은 프로퍼티들을 가지고 있다. ▼
간단하게 하나씩 보자.
color
`Container`자체에도 `color`가 있지만, `BoxDecoration`에도 있다.
"그럼 뭐가 우선?"
만약에 둘 다 `color` 프로퍼티를 갖게 되면, 우선이라고 할 거 없이 에러가 나게 된다. ▼
그리고 권장하는 메세지로 `BoxDecoration`의 `color`를 사용하라고 한다.
그렇기에 우선도를 따진다면 `BoxDecoration`의 `color`가 더 우선도가 높다.
borderRadius
`borderRadius`는 모서리 곡률을 넣는 프로퍼티다.
`BorderRadius`라는 클래스를 받고, `BorderRadius`에는 `all`, `circular`, `zero`, `horizontal`과 같은 메소드가 존재한다.
하나하나 다 보기엔 내용이 많기에 많이 사용하는 것들만 보면, 아래와 같이 사용할 수 있다.
`BorderRadius.all`은 모든 모서리에 매개변수로 들어간 Raidus 클래스를 적용시킨다.
아래의 코드는 `Radius.circular(8)`을 넣어 모든 모서리에 곡률 8을 적용시킨 예제다. ▼
Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.all(
Radius.circular(8),
),
),
alignment: Alignment.center,
child: Text("고라니"),
),
`BorderRadius.circular`는 모든 모서리에 Circular, 즉 원형 곡률을 적용한다.
기본적으로 `Radius.circular`를 사용하는 것이기에, 곡률만 넣어주면 된다. ▼
Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(8),
),
alignment: Alignment.center,
child: Text("고라니"),
),
`BorderRadius.zero`는 곡률을 아예 안넣는다는 의미다.
nullable 필드가 아니라 무조건 `BorderRadius`가 들어가야하는데 넣기 싫을 때, 이를 넣어주면 된다.
shape
shape는 컨테이너의 모양을 결정한다.
`BoxShape` enum을 받으며, `BoxShape`에는 `circle`과 `rectangle` 두개만 있다.
원형과 직사각형 둘만 있는데, 값을 안넣으면 기본적으로 `rectangle`로 설정되어있어서 사각형 형태로 잡힌다.
아래와 같이 넣으면 원으로 모양이 잡힌다. ▼
Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
)
다만 주의할 것이 있는데, `BoxShape`를 `circle`로 지정해놓으면 `borderRadius` 값을 비워놔야 한다.
만약에 비워놓지 않았다면 에러가 나게 된다. ▼
우선은 `BoxDecoration`의 프로퍼티는 이정도만 보도록 하고, 다음 포스트에서 더 자세하게 보는 것으로 하자.
Container의 크기에 대해
`Container`의 `width`와 `height`는 예상외로 nullable한 값이다.
크기가 무조건 지정이 되어야할 것만 같지만 꼭 지정해주지 않아도 된다.
그런데 지정을 하지 않으면 때로는 렌더링이 되기도 하고, 안되기도 하는 경우가 있다.
이를 자세히 알아두어야 그런 난감한 상황이 일어나지 않기에 하나씩 보자.
1. Container에 자식 위젯이 없을 때, width와 height도 없다면?
이 경우 `Container`는 부모 위젯의 크기에 맞추어 화면을 최대한 채우려고 한다.
이를 확인하기 위해 색상값만 넣어놓고 `Container`를 렌더링 해보면 화면을 꽉 채우게 된다.
현재 `body`부분에 넣어놓았는데, `Container`의 크기가 있는 부모 위젯은 `Scaffold`이기에 `Scaffold`의 `body`부분을 꽉 채우게 된다. ▼
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Container(
color: Colors.blue,
),
),
);
}
2. Container에 자식 위젯이 있을 때, width와 height가 없다면?
이 경우 `Container`는 자식 위젯에 최대한 맞게 크기가 잡히게 된다.
Container(
decoration: BoxDecoration(
color: Colors.red,
),
child: Text("고라니"),
)
3. width와 height가 설정되면?
`width`와 `height`가 설정되면 설정된 크기대로 따라가게 된다.
만약에 둘 중 하나만 설정된다면, 위의 두 규칙을 따르게 된다. ▼
Container(
width: 100,
decoration: BoxDecoration(
color: Colors.red,
)
)
결론적으로 요약을 하자면,
`width`와 `height`가 있다면 무조건 이 두 값을 따른다.
허나 두 값 중 없는 값은, 자식 위젯에 따라 다르게 배정이 된다.
자식 위젯이 있을 경우 자식 위젯에 맞게, 자식 위젯이 없을 경우 부모 위젯에 맞게.
마치며
여기까지 `Container`위젯에 대해 알아보았다.
내용이 이게 전부는 아니고 더 알아볼 것이 많지만 기초적인 내용은 거의 다 담았다고 생각한다.
'Develop > Flutter' 카테고리의 다른 글
[Flutter] 패키지 사용법 (0) | 2024.04.01 |
---|---|
[Flutter][Widget] Row, Column 위젯 (0) | 2024.03.24 |
[Flutter][Widget] Text 위젯 (0) | 2024.03.19 |
[Flutter][Widget] Step Indicator 구현 (0) | 2024.02.29 |
[Flutter][Error] Unhandled Exception: MissingPluginException (0) | 2024.02.28 |