[Day5] UI Layouts in Flutte 2 - Flutter for SwiftUI Developers 번역
Lay out multiple widgets vertically and horizontally
가장 일반적인 레이아웃 패턴 중 하나는 위젯을 세로 또는 가로로 배열하는 것입니다. Row 위젯을 사용하여 위젯을 가로로 정렬하고 Column 위젯을 사용하여 위젯을 세로로 정렬할 수 있습니다.
[요점]
- Row과 Column은 가장 일반적으로 사용되는 두 가지 레이아웃 패턴입니다.
- Row과 Column은 각각 자식 위젯의 리스트(List)를 받습니다.
- 자식 위젯(List)은 그 자체로 Row, Column 또는 기타 복잡한 위젯이 될 수 있습니다.
- Row과 Column이 자식 위젯을 세로 및 가로로 정렬하는 방법을 지정할 수 있습니다.
- 특정 자식 위젯을 늘리거나 제한할 수 있습니다.
- 자식 위젯이 Row 또는 Column의 사용 가능한 공간을 사용하는 방법을 지정할 수 있습니다.
Flutter에서 Row 또는 Column을 만들려면 Row 또는 Column 위젯에 자식 위젯 List를 추가합니다.
차례로 각 자식 위젯은 그 자체로 Row나 Column이 될 수 있습니다.
다음 예제는 Row 또는 Column 안에 또다른 Row 또는 Column을 중첩하는 방법을 보여줍니다.
이 레이아웃은 Row으로 구성됩니다. Row에는 왼쪽에 Column이 있고 오른쪽에 이미지가 있는 두 개의 자식이 있습니다:
왼쪽 Row의 위젯 트리에는 Row와 Column이 중첩되어 있습니다.
Row와 Column 중첩에 파블로바의 레이아웃 코드 일부를 구현합니다.
참고: Row와 Column은 가로 및 세로 레이아웃을 위한 아주 기초적인 기본 위젯으로, 이러한 낮은 수준(low level)의 위젯을 사용하면 최대한의 커스터마이징이 가능합니다.
Flutter는 필요에 따라 더 높은 수준의 위젯도 제공합니다.
예를 들어, Row 대신에 선행 및 후행 아이콘과 최대 3줄의 텍스트에 대한 속성이 있는 사용하기 쉬운 위젯인 ListTile을 사용할 수 있습니다.
Column 대신 콘텐츠가 너무 길어 사용 가능한 공간에 맞지 않을 경우 자동으로 스크롤되는 Column과 같은 레이아웃인 ListView를 선호할 수 있습니다.
자세한 내용은 일반적인 레이아웃 위젯을 참조하세요.
Aligning widgets(위젯 정렬)
mainAxisAlignment 및 crossAxisAlignment 속성을 사용하여 Row 또는 Column의 자식 정렬 방식을 제어할 수 있습니다.
Row의 경우 주축(mainAxisAlignment)은 가로로, 교차 축(crossAxisAlignment)은 세로로 정렬됩니다.
Column의 경우 주축(mainAxisAlignment)은 세로로, 교차 축(crossAxisAlignment)은 가로로 정렬됩니다.
MainAxisAlignment 및 CrossAxisAlignment 열거형은 정렬을 제어하기 위한 다양한 상수를 제공합니다.
다음 예시에서는 3개의 이미지 각각 너비가 100픽셀입니다.
렌더링 상자(이 경우 전체 화면)의 너비가 300픽셀을 초과하므로 main axis alignment(주축 정렬)을 spaceEvenly(공간균등)으로 설정하면 각 이미지의 앞과 뒤, 사이의 가로 크기가 균등하게 나뉩니다.
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Image.asset('images/pic1.jpg'),
Image.asset('images/pic2.jpg'),
Image.asset('images/pic3.jpg'),
],
);
Column은 Row과 동일한 방식으로 작동합니다.
다음 예는 각각 100픽셀 높이의 이미지 3개로 구성된 Column을 보여줍니다. 렌더링 상자의 높이(이 경우 전체 화면)가 300픽셀을 초과하므로 main axis alignment(주축 정렬)을 spaceEvenly(공간균등)으로 설정하면 각 이미지의 위, 가운데, 아래에 여유가 있는 공간이 균등하게 부여됩니다.
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Image.asset('images/pic1.jpg'),
Image.asset('images/pic2.jpg'),
Image.asset('images/pic3.jpg'),
],
);
Sizing widgets(위젯 크기 조정)
레이아웃이 너무 커서 장치에 맞지 않으면 영향을 받는 가장자리를 따라 노란색과 검은색 줄무늬 패턴이 나타납니다. 다음은 너무 넓은 Row의 예입니다:
Expanded 위젯을 사용하여 Row 또는 Column에 맞게 위젯의 크기를 조정할 수 있습니다. 이미지 Row가 렌더링 상자에 비해 너무 넓었던 이전 예제를 수정하려면 각 이미지를 Expanded 위젯으로 감싸면 됩니다.
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Image.asset('images/pic1.jpg'),
),
Expanded(
child: Image.asset('images/pic2.jpg'),
),
Expanded(
child: Image.asset('images/pic3.jpg'),
),
],
);
한 위젯이 형제 위젯보다 두 배의 공간을 차지하기를 원할 수 있습니다.
이를 위해 위젯의 flex 계수를 결정하는 정수인 Expanded 위젯 flex 속성을 사용하면 됩니다. 기본 flex 계수는 1입니다.
다음 코드는 가운데 이미지의 flex 계수를 2로 설정합니다:
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Image.asset('images/pic1.jpg'),
),
Expanded(
flex: 2,
child: Image.asset('images/pic2.jpg'),
),
Expanded(
child: Image.asset('images/pic3.jpg'),
),
],
);
Packing widgets
기본적으로 row 또는 column은 주축(main axis)을 따라 가능한 한 많은 공간을 차지하지만, 자식들을 서로 가깝게 패킹하려면 mainAxisSize를 MainAxisSize.min으로 설정합니다. 다음 예제에서는 이 속성을 사용하여 별 아이콘을 함께 패킹합니다.
Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
const Icon(Icons.star, color: Colors.black),
const Icon(Icons.star, color: Colors.black),
],
)
Nesting rows and columns
layout framework를 사용하면 row과 column을 또 다른 row과 column 안에 원하는 만큼 깊게 중첩할 수 있습니다. 다음 레이아웃의 개요 섹션에 대한 코드를 살펴봅시다:
위의 그림에서 빨간색 윤곽선 부분은 두 개의 Row로 구현됩니다. 평점 Row에는 별 5개와 리뷰 수가 포함됩니다. 아이콘 Row에는 아이콘과 텍스트의 세 Column이 포함됩니다.
평점 Row의 위젯 tree입니다:
ratings 변수는 별 5개 아이콘의 작은 Row와 텍스트를 포함하는 Row을 생성합니다:
var stars = Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
const Icon(Icons.star, color: Colors.black),
const Icon(Icons.star, color: Colors.black),
],
);
final ratings = Container(
padding: const EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
stars,
const Text(
'170 Reviews',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w800,
fontFamily: 'Roboto',
letterSpacing: 0.5,
fontSize: 20,
),
),
],
),
);
Tip : 중첩된 레이아웃 코드로 인해 발생할 수 있는 시각적 혼란을 최소화하려면 UI의 일부를 변수와 함수로 구현하세요.
평점 행 아래의 아이콘 Row에는 3개의 Column이 있으며, 위젯 tree에서 볼 수 있듯이 각 Column에는 아이콘과 두 줄의 Text가 포함되어 있습니다:
iconList 변수는 아이콘 Row를 정의합니다:
const descTextStyle = TextStyle(
color: Colors.black,
fontWeight: FontWeight.w800,
fontFamily: 'Roboto',
letterSpacing: 0.5,
fontSize: 18,
height: 2,
);
// DefaultTextStyle.merge()를 사용하면 자식에게 상속되는 기본 텍스트
// 스타일을 생성할 수 있으며, 이 스타일은 자식 및 모든 후속 자식에 상속됩니다.
final iconList = DefaultTextStyle.merge(
style: descTextStyle,
child: Container(
padding: const EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
Icon(Icons.kitchen, color: Colors.green[500]),
const Text('PREP:'),
const Text('25 min'),
],
),
Column(
children: [
Icon(Icons.timer, color: Colors.green[500]),
const Text('COOK:'),
const Text('1 hr'),
],
),
Column(
children: [
Icon(Icons.restaurant, color: Colors.green[500]),
const Text('FEEDS:'),
const Text('4-6'),
],
),
],
),
),
);
leftColumn 변수에는 평점과 아이콘 행은 물론 파블로바를 설명하는 제목과 텍스트가 포함되어 있습니다:
final leftColumn = Container(
padding: const EdgeInsets.fromLTRB(20, 30, 20, 20),
child: Column(
children: [
titleText,
subTitle,
ratings,
iconList,
],
),
);
왼쪽 열(left column)은 너비(width)를 제한하기 위해 SizedBox에 배치됩니다. 마지막으로, UI는 Card 안에 전체 행(왼쪽 열과 이미지 포함)으로 구성됩니다.
파블로바 이미지는 Pixabay에서 가져온 것입니다.
Image.network()를 사용하여 인터넷에서 이미지를 다운로드할 수 있지만, 이 예제에서는 프로젝트의 이미지 디렉터리에 이미지를 저장하고 pubspec 파일에 추가한 다음 Images.asset()을 사용하여 액세스합니다.
자세한 내용은 에셋 및 이미지 추가하기를 참조하세요.
에셋 및 이미지 추가하기 : https://docs.flutter.dev/ui/assets/assets-and-images
body: Center(
child: Container(
margin: const EdgeInsets.fromLTRB(0, 40, 0, 30),
height: 600,
child: Card(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 440,
child: leftColumn,
),
mainImage,
],
),
),
),
),
팁: 파블로바 예제는 태블릿과 같은 넓은 기기에서 가로로 실행하는 것이 가장 좋습니다.
iOS 시뮬레이터에서 이 예제를 실행하는 경우 하드웨어 > 장치 메뉴를 사용하여 다른 장치를 선택할 수 있습니다.
이 예제에서는 iPad Pro를 권장합니다. 하드웨어 > 회전을 사용하여 방향을 가로 모드로 변경할 수 있습니다. 창 > 크기 조정을 사용하여 시뮬레이터 창의 크기를 변경할 수도 있습니다(논리적 픽셀 수는 변경하지 않음).
https://docs.flutter.dev/ui/layout#lay-out-multiple-widgets-vertically-and-horizontally
'플러터 > 플러터 개념' 카테고리의 다른 글
[Day7] UI Layouts in Flutte 3 - Flutter for SwiftUI Developers 번역 (1) | 2023.11.10 |
---|---|
[Day6] UI Basics 3 - Flutter for SwiftUI Developers 번역 (0) | 2023.11.09 |
[Day4] UI Layouts in Flutte 1 - Flutter for SwiftUI Developers 번역 (0) | 2023.11.08 |
[Day3] UI Basics 2 - Flutter for SwiftUI Developers 번역 (0) | 2023.11.07 |
[Day2] UI Basics 1 - Flutter for SwiftUI Developers 번역 (0) | 2023.11.07 |