Flutter 기본 Widget

context·2023년 3월 27일
0

Flutter

목록 보기
2/7

Everything is Widget

위젯은 현재 주어진 상태(state)를 기반으로 어떤 UI를 구현할 지를 정의한다.
(React에서의 컴포넌트 개념이다.)

위젯의 상태가 변화하면 변경사항에 맞게, UI가 리렌더링된다.
이 때 플러터 프레임워크는 기존 위젯과 새로운 상태의 위젯을 비교해 UI 변화를 반영할 때, 필요한 최소한 변경 사항을 산출해 그린다. (최소한의 리소스 발생)

자식을 하나만 갖는 위젯과 여럿을 가지는 위젯으로 나뉜다.

자식을 하나만 갖는 대표 위젯

대체로 child 매개변수를 입력받는다.

  • Container : 자식을 담는 컨테이너, 배경색, 너비와 높이, 테두리 등 디자인 지정
  • GestureDetector : 제스처 기능을 자식 위젯에서 인식하는 위젯
    탭이나 드래그 , 더블 클릭 같은 제스처 기능이 자식 위젯에 인식될 때 함수 실행을 할 수 있다.
  • SizedBox : 높이와 너비를 지정하는 위젯. Container 위젯과 달리 디자인 요소는 적용할 수 없고, const 생성자로 선언해, 퍼포먼스 효율적

여럿 갖는 대표 위젯

대체로 children 매개 변수를 입력받으며, List로 여러 위젯 입력.

  • Column : Children 내 모든 위젯을 세로로 배치
  • Row : Children 내 모든 위젯을 가로로 배치
  • ListView : 리스트 구현 시 사용. children 매개변수에 다수의 위젯을 입력. 입력된 위젯이 화면을 벗어나게 되면 스크롤이 가능해진다.

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

Text("CODE", 
	style:  TextStyle(fontSize:16.0,
			fontWeight: FontWeight.w700,
			color: Colors.blue,)
,),

Gesture

JS에서의 Event를 Gesture로 칭하는 것 같다.

  • Button
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(Event)
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 : 확대 시작, 확대 중, 확대 끝났을 때 실행

Design

  • Container : 다른 위젯을 담는데 사용. 너비와 높이 지정 및 배경이나 테두리 추가
Container(
	decoration : BoxDecoration(
    	color: Colors.red, // 배경
        border: Border.all( // 테두리 적용
        	width: 16, // 테두리 굵기
            color: Colors.black, //테두리 색상
        ),
        borderRadius: BorderRadius.circular(16), // 모서리 둥글게
        height: 200,
        width: 100,
    )
)
  • SizedBox : 일반적으로 일정 크기 공간을 공백으로 두고 싶을 때
    Container와의 차이는 const 사용 시 퍼포먼스 이점
SizedBox(
	height: 200,
    width : 200,
    child : Container(color: Colors.red,),
)
  • Padding : child 위젯에 여백을 제공 / 상위 위젯과 하위 위젯 사이의 여백
Container(
	color: Colors.blue,
    child: Padding(
    	padding: EdgeInsets.all(16.0),
        child: Container(
        	color: Colors.red,
            width: 50,
            height: 50,
        )
    )
)

패딩은 부모 위젯 기준에서 크기 내부에 간격이 추가되는 것.
마진은 적용 위젯 기준 , 외부로 간격이 추가되는 것.

  • EdgeInsets

    EdgeInsets.all() : 상하좌우로 매개변수에 입력된 패딩 다 적용.
    EdgeInsets.symmetric(horizontal: 16, vertical: 16) : 가로와 세로 패딩 따로 적용
    EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0) : 다 따로 적용
    EdgeInsets.fromLTRB() : 포지셔널 파라미터로, 좌 위 우 아래 순서.

  • SafeArea
    아이폰의 노치같이 특이한 디자인을 위함. 노치에 위젯들을 가릴 수 있음.
    기기별 예외처리를 하지 않아도 안전한 화면에서만 위젯을 그림.

배치

하위 위젯을 가로 또는 세로로 배치하거나, 위젯 위에 위젯을 겹칠 때 사용한다.

Row(가로 배치) / Column(세로 배치)

하나의 child 위젯을 입력받는 위젯들과 달리, 여러 개의 children 매개변수를 노출한다.
Row와 Column에는 주축(Main Axis)와 반대축(Cross Axis)이라는 개념을 가진다.

Flexible

Row와 Column에서 사용되는 위젯, Flexible을 Column과 Row에서 사용하면 Flexible에 제공된 Child가 크기를 최소한으로 차지하게 할 수 있다.
또한, flex 매개변수를 통해, 각 Flexible 위젯이 얼만큼의 비율로 공간을 차지할 지 지정할 수 있다.

Column(
chidren: [
	Flexible(
    	//flex는 남은 공간을 차지할 비율 , flex값을 제공하지 않으면 기본값은 1.
        flex: 1,
        //파란색 컨테이너
        child: Container(
        	color: Colors.blue,
        )
    )
])

Expanded

Flexible 위젯을 상속하는 위젯. 위젯이 남아있는 공간을 최대한으로 차지한다.
기존 Flexible 위젯은 fit 매개변수에 FlexFit.tight 또는 .loose를 입력할 수 있다.
loose는 자식 위젯이 필요한 만큼의 공간만 차지한다.
tight는 자식 위젯이 차지하는 공간과 관계 없이 남은 공간을 모두 차지한다.
따라서, Expanded = FlexFit.tight

Column(
	children :[
	 	Expanded(
        	child : Container(
            	color: Colors.blue,
            )
        )   
    ]
)

Stack

위젯을 겹쳐준다.

Stack(
	children: [
     ... 
    ])

Transform Widget

Transformation을 전달함.

Transform.scale( // 주변 위젯들의 사이즈까지 건들지 않고 크기를 변경할 수 있다.
	scale: 5, // 배로 늘리는 것을 의미함
    child: const Icon(
    	Icons.~
        color: ~
        size: 98
    )
)

Transform.translate() : offset을 필수 파라미터로 갖는데, 좌표별로 위치를 움직인다.

이 때 같이 쓰기 좋은 프로퍼티는 clipBehavior
: 어떤 아이템이 overflow 됐을 때, 나머지 부븐을 어떻게 처리할 지 설정할 수 있다.
clipBehavior : clip.HardEdge는 나머지 부분을 다 잘라버림.

Reusable Widget

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가 아니기 때문에 유의.

0개의 댓글