23 01 18 WED
소다 학회 3일차
오늘의 목표
📍 어떤 Layout Widget들이 있고, 어떤 역할인지 빠르게 익힌다.
📍 code lab을 공부하며 직접 배운 내용을 적용해본다.
세션 11시
발표 3시
- Layout Widget 의 종류는?
Single-child , Multi- child 두 종류가 있음
< Single-child layout widgetsColumn class - Single-child layout은 child widget의 크기에 따라 크기를 조정하는 widget입니다. 하지만 선택적으로 크기를 조정할 수도 있기 때문에 어떤 widget의 쌓여져 있는지 잘 파악하고 공부해야합니다. >
<Multi-child layout widgets - Multi-child layout widgets은 하위 widget 항목을 레이아웃하는 widget입니다. Sigle-child layout은 하나의 child 라면 Mulit는 children 의 개념으로 여러개의 크기를 조정합니다. >
Column class 컬럼 클래스 (열) - Multi-child laydout widgets
자식을 수직으로 배열하는 클래스이다 .
수평 변형에 대해서는 Row(행) 에 대한 내용을 숙지하자.
사용 가능한 세로 공간을 채우도록 자식을 확장하려면 Expanded 위젯에서 자식을 래핑합니다.
열 위젯은 스크롤되지 않는다.
Troubleshooting (문제해결) *번외편 느낌이라고 생각하자.
When the incoming vertical constraints are unbounded
* 수직 조건에 대한 내용이 제한이 되지 않은 경우
Column 에 하나 이상의 Expanded 또는 Flexible 자식이 있고 다른 Column 또는 ListView 에 배치되거나 Column 에 대한 최대 높이 제약 조건을 제공하지 않는 다른 컨텍스트에 배치 되면,
유튜브 영상 속 내용
Flutter은 레이아웃을 빠르게 수행해야한다.
다른 화면말로 위젯을 효율적으로 배치해야함
single pass (단일 패스)
constraints go down (제약이 줄어듦)
geometry goes up (기하학이 올라감)
column > 자녀, (children)
한 아이가 Listveiw? 무한대로 크고 싶다 -> 최대한으로 커지고싶다
앱의 높이를 지정하지 않아 생기는 오류
column 크기 제한을 두지 않음
자식의 크기를 하고싶으면 크게 해도 됌
오류가 생기진 않지만, 해결할 수 있는 오류가 아님
-> 개발자가 원하는 레이아웃이 아닐 수 있음
지금처럼 오류가 뜨거나, 이상한 행동을 하지만 오류는 나지 않아 무슨 일이 일어난지 모르는 경우
Multi pass
flutter에서 높이를 지정하지 않아 생기는 문제에 대해서
최대 크기를 지정하지 않으면 돼
Listview -> SizedBox로 묶자
열(세로) 의 내용이 사용 가능한 공간을 초과하면, 이 세로의 내용이 넘쳐서 잘리게 된다.
일반적인 해결책으로는 Column 대신 --> Listview를 사용하여
세로 공간이 제한되어 있을때, 콘텐츠를 스크롤 할 수 있도록 하는 것임
Layout algorithm
레이아웃 알고리즘
프레임 워크에서 열을 렌더링 하는 방법을 알려줌
열 레이아웃은 6단계로 진행됌.
1. 무한한 수직 제약 조건, 수평 제약 조건을 각 자식(children)을 null 값이나 flex : 0 요소 < Expanded가 아닌 > 로 배치한다.
crossAxisAlignmnet (교차축) <
{
crossAxisAlignment 속성 <교차축>
5가지
1) crossAxisAlignment.star (시작)
교차 축의 시작 근처에 자식을 배치합니다. (행의 경우 상단, 열의 경우 왼쪽)
2) crossAxisAlignment.end (끝)
교차 축의 끝 근처에 자식을 배치합니다. (행의 맨 아래, 열의 오른쪽)
3) crossAxisAlignment.center (중간)
교차 축의 중간에 자식을 배치합니다. (행의 중간, 열의 중앙)
4) crossAxisAlignment.stretch (스트레치)
아이를 가로축에 걸쳐 펼칩니다. (행의 경우 위에서 아래로, 열의 경우 왼쪽에서 오른쪽으로)
5) crossAxisAlignment.baseline (기준선)
문자 기준선을 기준으로 자식을 정렬합니다.
텍스트 클래스만 해당되며 텍스트 기준선 속성이 텍스트 기준선으로 설정되어 있어야 한다.
}
이 crossAxisAlignment.stretch 이면 최대 너비와 일치하는 수평 제약 조건을 사용해야한다.
2.플렉스 요소가 (flex : 0)값이 아닌 요소 , 즉 Expanded가 있는 하위 요소 사이에 남아있는 세로 공간을 나눈다.
플렉스 자식의 플렉스 비율이 flex : 2.0 이라면, 플렉스 비율이 flex : 1.0인 자식보다 두 배의 수직 공간을 받게되는 것이다.
3. 1단계와 동일한 수평 제약 조건을사용해 나머지 자식을 각각 배치한다. 하지만 이때 수직 제약 조건을 사용함에 따라 2단계에서 할당된 공간의 양에 따라 조건을 사용한다.
FlexFit.tight 의 경우에 Flexible.fit 으로 할당된 공간을 가득 채우는 제약과,
FlexFit.loose의 경우에는 Flexible.fit 으로 느슨한 제약을 받는다.
4. column의 너비는 자식 최대 너비이다.
5. column 높이는 mainAxisSize (주축 정렬 ) 속성에 의해 결정된다.
6. mainAxisAlignment (주축 정렬) 및 crossAxisAlignment ( 교차축 ) 에 따라 각 자식의 위치를 결정한다.
+ ) 그 외
Row - 가로
Flex - 가로, 세로 배열을 원하는지 모르는 경우
Expanded - 나머지 공간을 모두 차지해야하는 하위 항목을 나타냄, 즉 꽉 채움)
flexble(SingleChildScrollView) - 문서 (스크롤 컨테이너 내) 에서 열(세로)를 사용하는 방법
Spacer - Flex 값에 비례해 공간을 차지하는 위젯
catarlog - 레이아웃 위젯
CustomMultiChildLayout class - Multi-child laydout widgets
: > 단일 자식의 레이아웃을 대표로 바꾸는 위젯
(대표(Delegate)를 설정하여 여러 자식의 크기와 위치를 결정하는 위젯)
대표(Delegate)는 각 자식에 대한 제약 조건을 결정할 수 있다. 대표자는 부모의 크기도 결정할 수 있지만, 부모의 크기는 자식의 크기에 따라 달라질 수 없다.
다시 말해, 대표자 > 부모 크기 결정 가능 / 부모 크기는 자식 크기에 결정되는 게 아니야. 왜? 더 하위 조건이거든
CustomMultiChildLayout은 여러 위젯의 크기와 위치 사이에 복잡한 관계가 있을 때 적합하다.
단일 자식의 레이아웃을 제어하려면, CustomSingleChildLayout 이 더 적합하다.
위젯을 다른 가장 자리에 정렬하는 경우에는, Stackd위젯이 더 적합하다.
대표자에 대한 위젯을 식별하려면, 각 child(하위)를 Layoutld 위젯에 래핑해야된다.
--> 여기서 래핑이란? Layoutld 안에 child(하위)를 감싸면 돼, 즉 하위를 안에 넣어
import 'package:flutter/material.dart';
void main() => runApp(const ExampleApp());
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Directionality(
// TRY THIS: Try changing the direction here and hot-reloading to
// see the layout change.
textDirection: TextDirection.ltr,
child: Scaffold(
body: ExampleWidget(),
),
),
);
}
}
/// Lays out the children in a cascade, where the top corner of the next child
/// is a little above (`overlap`) the lower end corner of the previous child.
///
/// Will relayout if the text direction changes.
class _CascadeLayoutDelegate extends MultiChildLayoutDelegate {
_CascadeLayoutDelegate({
required this.colors,
required this.overlap,
required this.textDirection,
});
final Map<String, Color> colors;
final double overlap;
final TextDirection textDirection;
// Perform layout will be called when re-layout is needed.
@override
void performLayout(Size size) {
final double columnWidth = size.width / colors.length;
Offset childPosition = Offset.zero;
switch (textDirection) {
case TextDirection.rtl:
childPosition += Offset(size.width, 0);
break;
case TextDirection.ltr:
break;
}
for (final String color in colors.keys) {
// layoutChild must be called exactly once for each child.
final Size currentSize = layoutChild(
color,
BoxConstraints(maxHeight: size.height, maxWidth: columnWidth),
);
// positionChild must be called to change the position of a child from
// what it was in the previous layout. Each child starts at (0, 0) for the
// first layout.
switch (textDirection) {
case TextDirection.rtl:
positionChild(color, childPosition - Offset(currentSize.width, 0));
childPosition +=
Offset(-currentSize.width, currentSize.height - overlap);
break;
case TextDirection.ltr:
positionChild(color, childPosition);
childPosition +=
Offset(currentSize.width, currentSize.height - overlap);
break;
}
}
}
// shouldRelayout is called to see if the delegate has changed and requires a
// layout to occur. Should only return true if the delegate state itself
// changes: changes in the CustomMultiChildLayout attributes will
// automatically cause a relayout, like any other widget.
@override
bool shouldRelayout(_CascadeLayoutDelegate oldDelegate) {
return oldDelegate.textDirection != textDirection ||
oldDelegate.overlap != overlap;
}
}
class ExampleWidget extends StatelessWidget {
const ExampleWidget({super.key});
static const Map<String, Color> _colors = <String, Color>{
'Red': Colors.red,
'Green': Colors.green,
'Blue': Colors.blue,
'Cyan': Colors.cyan,
};
@override
Widget build(BuildContext context) {
return CustomMultiChildLayout(
delegate: _CascadeLayoutDelegate(
colors: _colors,
overlap: 30.0,
textDirection: Directionality.of(context),
),
children: <Widget>[
// Create all of the colored boxes in the colors map.
for (MapEntry<String, Color> entry in _colors.entries)
// The "id" can be any Object, not just a String.
LayoutId(
id: entry.key,
child: Container(
color: entry.value,
width: 100.0,
height: 100.0,
alignment: Alignment.center,
child: Text(entry.key),
),
),
],
);
}
}
+ ) 그 외
MultiChildLayoutDelegate - 여러 자식의 레이아웃을 제어하는 대표
CustomSingleChildLayout - 단일 자식의 레이아웃을 대표로 바꾸는 위젯 (대표(Delegate)를 설정하여 여러 자식의 크기와 위치를 결정하는 위젯)
Stack - 컨테이너 가장자리를 기준으로 자식을 정렬
Flow - 변환 매트릭스를 사용해 자식의 페인트 시간 제어를 제공함
Flow class - Multi-child laydout widgets
FlowDelegate의 논리에 따라 자식의 크기와 크기를 효율적으로 지정하는 위젯
-> 그 논리가 뭐냐?
Delegate (대리자, 대표자) 라고 하는 것에 대한 각각의 파라미터 값을 지정함
그리고 그 값에 대한 내용이 바뀌면 그 바뀐 변화에 대해서 값을 저장하고 바뀜.
변환 매트릭스를 사용하여 하위 위치를 변경하는데 최적화되어 있음
flow container 의 크기는 대표의 FlowDelegate.getSize 함수에 의해 자식과 독립적으로 조정됩니다.
다음 하위는 FlowDelegate.getConstraintsForChild 함수의 제약 조건에 따라 독립적으로 크기가 조정된다.
레이아웃 중에 자식을 배치하는 대신 FlowDelegate.paintChildren 함수의 행렬을 사용하여 페인트 단계에서 변환 행렬을 사용하여 자식을 배치합니다.
자식을 다시 배치하지 않고 흐름을 다시 그리기만 하면 자식을 효율적으로 재배치할 수 있습니다. (배치 중에 크기 조정 및 위치 지정을 함께 수행 하는 Stack 과 대조)
Stack이란? 컨테이너 가장자리를 기준으로 자식을 정렬하는 것
흐름의 다시 그리기를 트리거하는 가장 효율적인 방법은 FlowDelegate 의 생성자에 애니메이션을 제공하는 것 입니다. 흐름은 이 애니메이션을 수신하고 애니메이션이 틱할 때마다 다시 그려서 파이프라인의 빌드 및 레이아웃 단계를 모두 피합니다.
FlowDelegate는 자식의 시각적 표시를 제어한다.
GridView class - Multi-child laydout widgets

스크롤 가능한 2D 위젯 배열
행과 열이 많은 복잡한 것 > 그리드를 만들자
count 가 많이 쓰임
우선 그리드 안에 들어가고싶은걸 정하자, 이후 그리드 안에 들어갈 count 계수를 정하는 것임
listView 처럼 스크롤 해서 항목을 확인할 수 있음
그리드의 주축 방향은 스크롤 하는 방향임(scrollDirection) , 세로로 스크롤 하면 세로인 Column이 주축이 되는 것
가장 일반적으로 많이 사용되는 그리드레이아웃은
교차축제 고정된 수의 타일이 있는 레이아웃을 만드는 GridView.count ,
최대 교차 축 범위가 있는 타일이 있는 레이아웃을 만드는 GridView.extent
맞춤 SilverGridDelegate는 정렬되지 않았거나 겹치는 배열을 포함해 자식의 임의의 2D 배열을 생성할 수 있다.
많은, 무한한 자식이 있는 그리드를 만드려면 gridDelegate에 대한 SliverGridDelegateWithFixedCrossAxisCount 또는 SliverGridDelegateWithMaxCrossAxisExtent 와 함께 GridView.builder 생성자를 사용한다.
SliverChildDelegate 클래스
작은 조각을 위해 아이들을 공급하는 대표.
padding? > 내용과 테두리 사이의 간격!
그럼 이 속성이란?
그리드 자체 대신 CustomScrollView.slivers 속성에 SliverPadding 이 있고 대신 SliverGrid가 SliverPadding 의 자식이 되도록 하는 것과 같습니다 .
코드가 CustomScrollView 를 사용하도록 포팅되면 SliverList 또는 SliverAppBar 와 같은 다른 조각을 CustomScrollView.slivers 목록 에 넣을 수 있습니다 .
+ ) 그 외
SingleChildScrollView - 단일자식이 있는 스크롤 기능 가능 위젯
ListView - 스크롤 가능한 선형 위젯 목록
PageView - 각각 뷰포트 크기인 하위 위젯의 스크롤 목록
CustomGridDelegateWithFixedCorssAxisCount - 교차 축에 타일 수가 고정된 레이아웃을 생성
ScrollNotification, NotificationListener은 ScrollController 을 사용하지 않고 스크롤 위치를 감시하는 데 사용할 수 있음
ListBody class - Multi-child laydout widgets
지정되니 축을 따라 자식을 순차적으로 정렬하여 다른 축의 부모 차원으로 강제 정렬하는 위젯
이 위젯은 직접 거의사용되지 않는다 -> 다른 위젯과 함께 쓰인다 (종속 개념)
SingleChildScrollView - 콘텐츠를 스크롤 할 수 있도록 하기 위해 ListBody와 함께 사용되는 경우 많음
이 레이아웃 알고리즘의 보다 정교한 버전을 구현하는 Column, Row (행, 열)
ListView - ListBody class레이아웃 알고리즘을 효율적으로 스크롤 버전 구현함
- SingleChildScrollView , 콘텐츠를 스크롤할 수 있도록 하기 위해 ListBody 와 함께 사용되는 경우가 있습니다.
- 이 레이아웃 알고리즘의 보다 정교한 버전을 구현하는 Column 및 Row (약간 덜 효율적인 비용으로).
- 이 레이아웃 알고리즘의 효율적인 스크롤 버전을 구현하는 ListView .
ListView class - Multi-child laydout widgets
가장 일반적으로 사용되는 스크롤 위젯
스크롤 방향으로 자식을 차례대로 표시한다.
교차 축 Axis에서 나온 자식은 ListView를 채우는 데 필요하다.
null 이 아닌 경우 ItemExtents는 자식이 스크롤 방향에서 지정된 범위를 갖도록한다.
null이 아닌 경우, prototpeItem은 자식이 스크롤 방향에서 지정된 위젯과 동일한 범위를 갖도록 한다.
아주 간편한 방법으로 정리할 수 있음
원하는 대로 제작 가능
수직으로, 수평으로 바꾸면 됌 스크롤 방향은
상향식 접근법? 리버스로 하면돼
스크롤 되지 않도록 해? neverscroll
화면 밖에 것들/?? 캐시로 해
동적인 거 원해? 할 수 있음
itemExtent 또는 prototypeItem을 지정하는 것이 하위 항목이 자신의 범위를 결정하도록 하는 것 보다 효율적이다.
ListView.builder 를 구성하는 데에는 4가지 옵션이 있음.
1. 기본 생성자는 자식의 List<Widget> 을 사용함.
2. ListView.builder 생성자는 필요에 따라 자식을 빌드하는 indexWidgetBuilder 를 용한다.
빌더는 실제로 표시되는 자식에 대해서만 호출됨.
3. ListView.separated 생성자는 두개의 IndexedWidgetBuilder 를 사용한다.
4. ListView.custom 생성자는 자식 모델의 추가 측면을 사용자 지정하는 기능을 제공하는 SilverChildDelegate를 사용한다.
단일 자식이 있는 스크롤 가능 기능 위젯인 SingleChildScrollWidget
PageView = 각각 뷰포트 크기인 하위 위젯의 스크롤 목록이다.
01 18 발표
column - Multi
Row -Multi
sizedbox - Single
stack - Multi
sliverappbar -
column (열) ㅇㅇ
Row (행)ㅇㅇ
sizedbox(상자박스)
stack
sliverappbar
1. Column - 열
자식을 수직으로 배열하는 클래스이다 . (세로)
열 위젯은 스크롤되지 않는다.
사용 가능한 세로 공간을 채우도록 자식을 확장하려면 Expanded 위젯에서 자식을 래핑한다.

코드를 확인해보자.
Column(
children: const <Widget>[
Text('Deliver features faster'),
Text('Craft beautiful UIs'),
Expanded(
child: FittedBox(
child: FlutterLogo(),
),
),
],
)
Expanded 안에 child(자식) 를 래핑 한 것을 확인할 수 있다.
ㄴ 래핑이란? wrapping 감싸다.


2. Row - 행
자식을 수평 배열로 표시하는 위젯이다. ( 가로 )
행 위젯은 스크롤되지 않는다.
이 위젯을 사용하기 위해서는, 사용 가능한 가로 공간을 채우도록 자식을 확장해야하는데, Expanded 위젯에서 자식을 래핑한다.

코드를 확인해보자.
Row(
children: const <Widget>[
Expanded(
child: Text('Deliver features faster', textAlign: TextAlign.center),
),
Expanded(
child: Text('Craft beautiful UIs', textAlign: TextAlign.center),
),
Expanded(
child: FittedBox(
child: FlutterLogo(),
),
),
],
)
Expanded 안에 두개의 자식( child ) 를 래핑 한 것을 확인할 수 있다.
3. Sizedbox - 상자 박스
지정된 크기의 상자다.
ㄴ 정확한 수치를 알고 쓸 때 사용
자식이 주어지면 이 위젯은 특정 너비 / 높이를 갖도록 되어있다.
이 위젯의 부모가 허용하지 않은 경우 값이 무시된다.
자식이 부모와 같은 크기가 되는 것을 , 화면이 된다고 말하는데,
이런 값은 무시가 된다.

width, height 값이 각각 200.0 과 300.0 으로 정확한 크기를 만든다.
특징
✅상위요소에서 허용되는 만큼 확장된다.
✅위젯 간 여유 공간 확보에 도움이 된다.
✅하위요소까지 같은사이즈가 되게끔 한다.
✅렌더링없이 공간 채울 수 있다.
ㄴ렌더링이란?
컴퓨터 프로그램을 사용하여 모델 또는 이들을 모아둔 장면인 scene 파일로부터 영상을 만드는 과정을 말함
쉽게 이해하면, 사진을 모아서 영상을 만든다고 생각하면 된다.
4. Stack
= 힌마디로 쌓는거야
// 우리가 대학원 갈라고, 취업할라고 해 그럼 뭘 쌓아?
"스팩(SPEC)을 쌓지"
그런 느낌인거야 계속 중복해서 그 위에 쌓고 쌓고 쌓아
근데 약간 비슷한 결 인거지, 스팩이 아니라 여긴 스택.
자식을 상자의 가장자리를 기준으로 자식으로 배치하는 위젯.
-> 여기서 Stack의 자식이란?
positioned , non-positioned 이다.
positioned 위젯을 사용하기 위해서는, Stack 내에서 특정 하위 요소에 특정 위치를 지정할 수 있다.
예를 들면,
Stack(
children: <widget> [
myGrayBox,
myRedBox,
Posiotioned(
bottom: 0;
right: 0;
child: myGreenBox.
),
myBlueBox,
myYellowBox,
],
)
이렇게 bottom, right 값을 지정해서 포지션 해줄 수 있다.
특징
✅'여러 자식을 겹치려는 경우' 에 유용함.
✅중복이 가능함! <다른 위젯에 덮어씀>
✅위젯 리스트를 가지고 밑에서부터 사용
✅스택 모든 하위 요소는 topstart로 결정됌

Stack(
children: <Widget>[
Container(
width: 100,
height: 100,
color: Colors.red,
),
Container(
width: 90,
height: 90,
color: Colors.green,
),
Container(
width: 80,
height: 80,
color: Colors.blue,
),
],
)
5. Silverappbar 실버 아니고 슬라이버 임
CustomScrollView와 통합되는 머티리얼 디자인 앱 바.
앱 바에 맞춤식 스크롤 움직임을 제공함
인스타그램의 경우 처음 초기 화면에서 사람들의 스토리가 보이는데, 스크롤을 해서 믿으로 내리다보면, 그 스토리가 사라지고 사람들이 올린 게시물 화면만 디스플레이 상에 뜨게 된다.


- copyright 개발자 김솔미