Everything is Widget
위젯은 현재 주어진 상태(state)를 기반으로 어떤 UI를 구현할 지를 정의한다.
(React에서의 컴포넌트 개념이다.)
위젯의 상태가 변화하면 변경사항에 맞게, UI가 리렌더링된다.
이 때 플러터 프레임워크는 기존 위젯과 새로운 상태의 위젯을 비교해 UI 변화를 반영할 때, 필요한 최소한 변경 사항을 산출해 그린다. (최소한의 리소스 발생)
자식을 하나만 갖는 위젯과 여럿을 가지는 위젯으로 나뉜다.
대체로 child 매개변수를 입력받는다.
대체로 children 매개 변수를 입력받으며, List로 여러 위젯 입력.
child와 children 매개변수에 지속적으로 하위 위젯을 가지면, Widget Tree 구조로 구성이 된다. (child와 children을 동시에 받는 위젯은 존재하지 않음.)
//기본적인 트리구조
void main(){
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: SizedBox(
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment: center,
children: [Text('code'),Text("code')]
)
)
)
)
)
}
Text("CODE",
style: TextStyle(fontSize:16.0,
fontWeight: FontWeight.w700,
color: Colors.blue,)
,),
JS에서의 Event를 Gesture로 칭하는 것 같다.
TextButton( // 이 외 OutlineButton , ElevatedButton
onPressed: () {}, // event callback
style : TextButton.styleFrom(
foregroundColor: Colors.red,
),
child: Text("텍스트 버튼")
)
// 추가적으로 IconButton
IconButton(
onPressed: (){},
icon: Icon(Icons.home), // Icons 클래스에 플러티 기본 아이콘 존재.
)
// FloatingActionButton - Material Design에서 추구하는 버튼 형태
class FloatingActionButtonEx extends StatelessWidget{
@override
Widget build(BuildContext context){
return MaterialApp(
home : Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Text("클릭"),
),
body: Container(),
)
)
}
}
GestureDetector(
onTab: (){
print('tab');
},
onDoubleTab: (){
print('double');
},
child: Container( // 제스처가 적용되는 위젯을 child로 적용.
decoration: BoxDecoration(
color: Colors.red,
),
width: 100,
height: 100,
)
)
onTab : 한 번 탭
onDoubleTab : 두 번 연속 탭
onLongPress : 길게 누르기
onPanStart : 수평 또는 수직으로 드래그 시작될 때
onPanUpdate : 수평 또는 수직으로 드래그 하는 동안 드래그 위치 업데이트 시
onPanEnd : 수평 또는 수직으로 드래그 끝났을 때 실행
onHorizontalDragStart : 수평으로 드래그 시작 시 실행
onHorizontalDragUpdate : 수평으로 드래그 중 드래그 위치가 업데이트될 때
onHorizontalDragEnd : 수평으로 드래그가 끝났을 때
.. 수직은 onVertical~
onScaleStart / onScaleUpdate / onScaleEnd : 확대 시작, 확대 중, 확대 끝났을 때 실행
Container(
decoration : BoxDecoration(
color: Colors.red, // 배경
border: Border.all( // 테두리 적용
width: 16, // 테두리 굵기
color: Colors.black, //테두리 색상
),
borderRadius: BorderRadius.circular(16), // 모서리 둥글게
height: 200,
width: 100,
)
)
SizedBox(
height: 200,
width : 200,
child : Container(color: Colors.red,),
)
Container(
color: Colors.blue,
child: Padding(
padding: EdgeInsets.all(16.0),
child: Container(
color: Colors.red,
width: 50,
height: 50,
)
)
)
패딩은 부모 위젯 기준에서 크기 내부에 간격이 추가되는 것.
마진은 적용 위젯 기준 , 외부로 간격이 추가되는 것.
EdgeInsets.all() : 상하좌우로 매개변수에 입력된 패딩 다 적용.
EdgeInsets.symmetric(horizontal: 16, vertical: 16) : 가로와 세로 패딩 따로 적용
EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0) : 다 따로 적용
EdgeInsets.fromLTRB() : 포지셔널 파라미터로, 좌 위 우 아래 순서.
하위 위젯을 가로 또는 세로로 배치하거나, 위젯 위에 위젯을 겹칠 때 사용한다.
하나의 child 위젯을 입력받는 위젯들과 달리, 여러 개의 children 매개변수를 노출한다.
Row와 Column에는 주축(Main Axis)와 반대축(Cross Axis)이라는 개념을 가진다.
Row와 Column에서 사용되는 위젯, Flexible을 Column과 Row에서 사용하면 Flexible에 제공된 Child가 크기를 최소한으로 차지하게 할 수 있다.
또한, flex 매개변수를 통해, 각 Flexible 위젯이 얼만큼의 비율로 공간을 차지할 지 지정할 수 있다.
Column(
chidren: [
Flexible(
//flex는 남은 공간을 차지할 비율 , flex값을 제공하지 않으면 기본값은 1.
flex: 1,
//파란색 컨테이너
child: Container(
color: Colors.blue,
)
)
])
Flexible 위젯을 상속하는 위젯. 위젯이 남아있는 공간을 최대한으로 차지한다.
기존 Flexible 위젯은 fit 매개변수에 FlexFit.tight 또는 .loose를 입력할 수 있다.
loose는 자식 위젯이 필요한 만큼의 공간만 차지한다.
tight는 자식 위젯이 차지하는 공간과 관계 없이 남은 공간을 모두 차지한다.
따라서, Expanded = FlexFit.tight
Column(
children :[
Expanded(
child : Container(
color: Colors.blue,
)
)
]
)
위젯을 겹쳐준다.
Stack(
children: [
...
])
Transformation을 전달함.
Transform.scale( // 주변 위젯들의 사이즈까지 건들지 않고 크기를 변경할 수 있다.
scale: 5, // 배로 늘리는 것을 의미함
child: const Icon(
Icons.~
color: ~
size: 98
)
)
Transform.translate() : offset을 필수 파라미터로 갖는데, 좌표별로 위치를 움직인다.
이 때 같이 쓰기 좋은 프로퍼티는 clipBehavior
: 어떤 아이템이 overflow 됐을 때, 나머지 부븐을 어떻게 처리할 지 설정할 수 있다.
clipBehavior : clip.HardEdge는 나머지 부분을 다 잘라버림.
class Button extends StatelessWidget{
final String text;
final Color bgColor; // Color, IconData 다 지원.
final Color textColor;
}
const Button({ // 생성자
super.key,
required this.text;
required ths.bgColor;
required this.textColor,
})
@override
Widget build~{}
하드코딩 된 값들은 const겠지만, props로 받는 value들은 const가 아니기 때문에 유의.