
1. 박스 1개 만들기

- double.infinity는 무한대

2. 박스 3개 만들기
- 컬럼은 세로 정렬
- 로우는 가로 정렬
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:recipe_app2/components/recipe_menu_item.dart';
import '../components/recipe_body.dart';
import '../components/recipe_menu.dart';
import '../components/recipe_title.dart';
class RecipePage extends StatelessWidget {
const RecipePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.blue,
width: 50,
height: 50,
),
Container(
color: Colors.yellow,
width: 50,
height: 50,
)
],
), // 새로 방향 레이아웃 -> 자식이 없을때 크기 : 0, 0, 0, 0
);
}
AppBar _appbar() {
return AppBar(
actions: [
Icon(CupertinoIcons.search),
//시그니처 매개변수 키 값이 없다, 그 위젯의 핵심은 시그니처로 키 값을 넣지 않는다.
SizedBox(width: 15),
Icon(
CupertinoIcons.heart,
color: Colors.redAccent,
),
SizedBox(width: 15),
],
);
}
}

- 컬럼 // 세로 : 블락, 가로 : 인라인
- 로우 // 가로 : 블락, 세로 : 인라인
- 자식이 큰게 들어오면 다 깨짐 → 컬럼 자체를 미리 키워놔야 함

- 컨테이너는 끝까지 차지함
- 자식이 없으면 블락
- 자식이 있으면 인라인


- ListView는 최소 값이 가로가 double.infinity라서 width가 안보임
크기를 조절하려면 부모를 만들어서 크기 조절하기

3. 외워야함!!
ㅤ | 인라인 | 블락 | 스타트 | 센터 |
Colum | 가로 | 세로 | 세로 | 가로 |
Row | 세로 | 가로 | 가로 | 세로 |
Container | 자식O | 자식 X | ㅤ | ㅤ |
ListView | 세로 | 세로 | ㅤ | ㅤ |
4. 서로에게 영향 안받도록 배치하기
- 로우는 가로 정렬
crossAxisAlignment: CrossAxisAlignment.start // 왼쪽에서 시작
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../components/recipe_title.dart';
class RecipePage extends StatelessWidget {
const RecipePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.blue,
width: 50,
height: 50,
),
Row(
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.blue,
width: 50,
height: 50,
),
],
),
],
),
);
}
AppBar _appbar() {
return AppBar(
actions: [
Icon(CupertinoIcons.search),
SizedBox(width: 15),
Icon(
CupertinoIcons.heart,
color: Colors.redAccent,
),
SizedBox(width: 15),
],
);
}
}

5. 각각 독립된 영역으로 구분하기
- 서로 영향을 주고 받지 않도록 해야 디자인이 깨지지 않음
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../components/recipe_title.dart';
class RecipePage extends StatelessWidget {
const RecipePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.blue,
width: 50,
height: 50,
),
Row(
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.blue,
width: 50,
height: 50,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
color: Colors.yellow,
width: 50,
height: 50,
),
],
),
],
),
);
}
AppBar _appbar() {
return AppBar(
actions: [
Icon(CupertinoIcons.search),
SizedBox(width: 15),
Icon(
CupertinoIcons.heart,
color: Colors.redAccent,
),
SizedBox(width: 15),
],
);
}
}

- 영역이 나뉘어져 있음
- 각 영역마다 3개의 컴포넌트로 나눠야 함
- 컴포넌트끼리 다 독립적이지 않아서 영향을 받는 것 → 완전히 독립시켜야 함
- 전체는 컬럼 : 위에서 아래로
내부에 컴포넌트 각각 3개로 구분

6. 디자인이 안 무너지게 설계하기
- 컴포넌트로 뺀 후 타입을 변경한 경우 부모의 타입으로 바꿔줘야 오류가 나지 않음
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../components/recipe_title.dart';
class RecipePage extends StatelessWidget {
const RecipePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
// 전체 디자인
// 총 3개의 섹션
children: [
_top(),
Row(
children: [
Container(
color: Colors.red,
width: 50,
)
],
)
],
),
);
}
Widget _top() { // 부모 타입으로 변경하기
return Container(
width: double.infinity,
child: Column(
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.yellow,
width: 50,
height: 50,
)
],
),
);
}
AppBar _appbar() {
return AppBar(
actions: [
Icon(CupertinoIcons.search),
SizedBox(width: 15),
Icon(
CupertinoIcons.heart,
color: Colors.redAccent,
),
SizedBox(width: 15),
],
);
}
}

- top 디자인하기
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../components/recipe_title.dart';
class RecipePage extends StatelessWidget {
const RecipePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
// 전체 디자인
// 총 3개의 섹션
children: [
_top(),
Row(
children: [
Container(
color: Colors.red,
width: 50,
)
],
)
],
),
);
}
Widget _top() { // 부모 타입으로 변경하기
return Container(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.yellow,
width: 50,
height: 50,
)
],
),
);
}
AppBar _appbar() {
return AppBar(
actions: [
Icon(CupertinoIcons.search),
SizedBox(width: 15),
Icon(
CupertinoIcons.heart,
color: Colors.redAccent,
),
SizedBox(width: 15),
],
);
}
}



- 하나만 길이가 다른 경우
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
// 전체 디자인
// 총 3개의 섹션
children: [
_top(),
Row(
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.yellow,
width: 50,
height: 100,
)
],
)
],
),
);
}
Widget _top() { // 부모 타입으로 변경하기
return Container(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.yellow,
width: 50,
height: 50,
)
],
),
);
}


@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
// 전체 디자인
// 총 3개의 섹션
children: [
_top(),
Container(
height: 100, // 자식의 크기에 맞추려면 자식 각각에 높이를 주면 됨
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: double.infinity,
),
Container(
color: Colors.green,
width: 50,
height: double.infinity,
),
Container(
color: Colors.yellow,
width: 50,
height: double.infinity,
)
],
),
)
],
),
);
- 자식의 높이는 infinity로 맞추고 부모의 길이 조절하기



@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
// 전체 디자인
// 총 3개의 섹션
children: [
_top(),
_center(),
Container(
width: 50,
height: 50,
child: Container(
color: Colors.red,
),
)
],
),
);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
// 전체 디자인
// 총 3개의 섹션
children: [
_top(),
_center(),
Center(
child: Container(
width: 50,
height: 50,
child: Container(
color: Colors.red,
),
),
),
],
)
);
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
// 전체 디자인
// 총 3개의 섹션
children: [
_top(),
_center(),
Container(
width: double.infinity,
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
],
),
),
],
)
);
}

무너지지 않는 디자인 만들기
- 앱은 가로 사이즈가 제일 중요함
- 세로 크기는 안에 있는 자식의 크기에 맞춘 것이기에 신경쓸 필요 없음
Widget _top() {
// 부모 타입으로 변경하기
return SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.yellow,
width: 50,
height: 50,
)
],
),
);
}
- top은 colum → 가로 : 인라인 → 늘려주기
높이 : 자식의 크기에 맞추기
- 박스로 감싸는 이유는 가로 설계 때문 → 로우는 그대로 두기


@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
// 전체 디자인
// 총 3개의 섹션
children: [
_top(), // 새로로 내려감
_center(),
Align(
alignment: Alignment.centerRight,
child: Container(
color: Colors.red,
width: 50,
height: 50,
),
),
],
)
);
}

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import '../components/recipe_title.dart';
class RecipePage extends StatelessWidget {
const RecipePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
// 전체 디자인
// 총 3개의 섹션
children: [
_top(),
_center(),
_bottom(),
],
)
);
}
Widget _bottom() {
return Align(
alignment: Alignment.center,
child: Container(
color: Colors.red,
width: 50,
height: 50,
),
);
}
Widget _center() {
return Row( // 부모로 감싸는 이유는 가로 설계 때문
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.yellow,
width: 50,
height: 50,
)
],
);
}
Widget _top() {
// 부모 타입으로 변경하기
return SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.yellow,
width: 50,
height: 50,
)
],
),
);
}
AppBar _appbar() {
return AppBar(
actions: [
Icon(CupertinoIcons.search),
SizedBox(width: 15),
Icon(
CupertinoIcons.heart,
color: Colors.redAccent,
),
SizedBox(width: 15),
],
);
}
}


[ 노란색을 가운데 두고 싶다 ]

다시 Row로 감싼다 (컨테이너에 alt + enter)


근데 이렇게 하면 안 됨
why?

배치할 때, 독립적이지 않으니까 모두 영향을 받는다.
독립적으로 디자인해야 함! 지금 컬럼 안에 다 때려넣었잖아.
전체도 컬럼, 안에 세부(?)도 컬럼.
이 3개가 컬럼 안에 묶여야지 컴포넌트화 시킬 수 있음
[ 전체 코드 ] - 다음에 연습
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:recipe_app/components/recipe_body.dart';
import 'package:recipe_app/components/recipe_menu.dart';
import 'package:recipe_app/components/recipe_menu_item.dart';
import '../components/recipe_title.dart';
class RecipePage extends StatelessWidget {
const RecipePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.blue,
width: 50,
height: 50,
),
Row(
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.blue,
width: 50,
height: 50,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
color: Colors.yellow,
width: 50,
height: 50,
),
],
),
],
),
);
}
AppBar _appbar() {
return AppBar(
actions: [
Icon(CupertinoIcons.search),
SizedBox(width: 15),
Icon(
CupertinoIcons.heart,
color: Colors.redAccent,
),
SizedBox(width: 15),
],
);
}
}
이건 컴포넌트화 불가능. 독립되어 있지 않음.
따로 박스 설계를 하지 않으면 디자인이 무너질 것
[ 제대로 설계 Column ]

섹션이 총 3개!

이런 식으로 디자인이 나와야 함

다 만들었으니 애를 컴포넌트로 빼자 (컴포넌트로 빼는게 맞는데 지금은 수업한다고 Method로 뺌)


컨테이너로 감싸고, 리턴 타입을 Widget (부모)로 바꿔준다.


독립됨
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:recipe_app/components/recipe_body.dart';
import 'package:recipe_app/components/recipe_menu.dart';
import 'package:recipe_app/components/recipe_menu_item.dart';
import '../components/recipe_title.dart';
class RecipePage extends StatelessWidget {
const RecipePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
children: [
_top(),
Row(),
],
),
);
}
Widget _top() {
return Container(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.yellow,
width: 50,
height: 50,
),
],
),
);
}
AppBar _appbar() {
return AppBar(
actions: [
Icon(CupertinoIcons.search),
SizedBox(width: 15),
Icon(
CupertinoIcons.heart,
color: Colors.redAccent,
),
SizedBox(width: 15),
],
);
}
}
Row

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class RecipePage extends StatelessWidget {
const RecipePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
children: [
_top(),
Container(
height: 200,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: double.infinity,
),
Container(
color: Colors.green,
width: 50,
height: double.infinity,
),
Container(
color: Colors.yellow,
width: 50,
height: double.infinity,
),
],
),
),
],
),
);
}
Widget _top() {
return Container(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.yellow,
width: 50,
height: 50,
),
],
),
);
}
AppBar _appbar() {
return AppBar(
actions: [
Icon(CupertinoIcons.search),
SizedBox(width: 15),
Icon(
CupertinoIcons.heart,
color: Colors.redAccent,
),
SizedBox(width: 15),
],
);
}
}
어휴 ssi bv
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class RecipePage extends StatelessWidget {
const RecipePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
children: [
_top(),
_center(),
Container(
width: double.infinity,
height: 50,
child: Container(
color: Colors.red,
width: 50,
height: double.infinity,
),
),
],
),
);
}
Container _center() {
return Container(
height: 200,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: double.infinity,
),
Container(
color: Colors.green,
width: 50,
height: double.infinity,
),
Container(
color: Colors.yellow,
width: 50,
height: double.infinity,
),
],
),
);
}
Widget _top() {
return Container(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.yellow,
width: 50,
height: 50,
),
],
),
);
}
AppBar _appbar() {
return AppBar(
actions: [
Icon(CupertinoIcons.search),
SizedBox(width: 15),
Icon(
CupertinoIcons.heart,
color: Colors.redAccent,
),
SizedBox(width: 15),
],
);
}
}


height는 박스로 감싸서 크기 줄 필요 없음
Column은 늘리고, Row는 그대로 둔다.
Column은 왜 늘릴까? 처음에 Row가 들어갈 수 있는 경우도 있겠지

center를 두든, 뭘 두든…
[ Align ]



끝까지 차지하기 위해선 컬럼은 SizedBox 사용
return 타입은 전부 위젯
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class RecipePage extends StatelessWidget {
const RecipePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Column(
children: [
_top(),
_center(),
_bottom(),
],
),
);
}
Align _bottom() {
return Align(
alignment: Alignment.centerRight,
child: Container(
color: Colors.red,
width: 50,
height: 50,
),
);
}
Widget _center() {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.yellow,
width: 50,
height: 50,
),
],
);
}
Widget _top() {
return SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
),
Container(
color: Colors.green,
width: 50,
height: 50,
),
Container(
color: Colors.yellow,
width: 50,
height: 80,
),
],
),
);
}
AppBar _appbar() {
return AppBar(
actions: [
Icon(CupertinoIcons.search),
SizedBox(width: 15),
Icon(
CupertinoIcons.heart,
color: Colors.redAccent,
),
SizedBox(width: 15),
],
);
}
}

배치는 Block을 만든다.
세로를 Block으로
- 컨테이너는 제약조건을 줄 수 있음
부모가 자식에게 제약 조건을 검 → 부모의 제약 조건을 알아야하기에 동적임
- 제약 조건을 모든 위젯이 들고 있는 것은 아님
sizesBox는 없음
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:recipe_app/components/recipe_body.dart';
import 'package:recipe_app/components/recipe_menu.dart';
import 'package:recipe_app/components/recipe_menu_item.dart';
import '../components/recipe_title.dart';
class RecipePage extends StatelessWidget {
const RecipePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appbar(),
body: Container(
constraints: BoxConstraints(
minWidth: 100,
minHeight: 100,
maxWidth: 150,
maxHeight: 300,
),
child: Container(
alignment: Alignment.center,
color: Colors.red,
width: 1000,
height: 1000,
),
),
);
}
AppBar _appbar() {
return AppBar(
actions: [
Icon(CupertinoIcons.search),
SizedBox(width: 15),
Icon(
CupertinoIcons.heart,
color: Colors.redAccent,
),
SizedBox(width: 15),
],
);
}
}
Share article