플러터는 모든 것이 위젯이다!
Scaffold
Material Design의 앱 구조를 구성하는 데 사용되는 가장 중요한 위젯 중 하나
화면을 구성할 때 사용되며, AppBar, Body, Drawer, BottomNavigationBar, FloatingActionButton 등의 여러 구성 요소를 포함
Scaffold는 각 화면의 기본적인 레이아웃을 정의하고, Navigator를 통해 화면을 전환
StatelessWidget
build 메서드를 통해서 UI를 출력하는 위젯
(👏 stl을 입력하면 자동으로 전체 구조를 입력할 수 있다)
블록처럼 위젯에 위젯을 쌓아가면서 앱을 만드는 것
모든 위젯은 build 메서드를 사용해야한다
모든 앱은 cuperinoApp(ios) 혹은 MaterialApp(google)중에 선택해야하는데, MaterialApp이 보기 좋다
모든 화면은 Scaffold(구조)를 가져야한다
import 'package:flutter/material.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Hello flutter!"),
),
body: Center(
child: Text("hello world"),
),
),
);
}
}
TransformationWidget
=>화면을 조정할 수 있는 위젯 Transform.scale(
scale: 2.2,
child: Transform.translate(
offset: const Offset(8, 15),
child: const Icon(
Icons.euro_rounded,
color: Colors.white,
size: 88,
),
),
)
clipBehavior
clipBehavior: Clip.hardEdge
를 카드부분에 사용해주면 overflow된 부분을 조작할 수 있게 해준다
SingleChildScrollView
스크롤 기능
StatefulWidget
위젯에 데이터를 저장하고 실시간으로 데이터의 변화를 보고 싶을때 사용
상태를 가지고 있는 위젯으로 상태에 따라 변하게 될 데이터를 생각할 수 있다! 약간 React의 상태관리같은 느낌쓰?
class _AppState extends State<App>{
int counter=0;
void onClicked(){
setState((){ //상태관리해주는 부분
counter=counter+1;
});
}
Widget build(BuildContext context){
return MaterialAPP(
home:Scaffold(
body:Center(
child:Column(
childern:[
const Text("click count")
Text(
"$counter"
),
],
),
),
),
),
},
}
Expanded
시작화면부터 끝까지 확장
GestureDetector
대부분의 동작을 감지
탭,마우스이동, 드래그, 줌 등을 감지
ex) onTap()
MaterialPageRoute
return GestureDetector(
onTap: () { //탭을감지
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailScreen(
title: title,
thumb: thumb,
id: id,
),
),
);
},
Hero
shared element transition
Hero는 두 화면 사이에 애니메이션을 주는 컴포넌트
두 화면에 모두 필수값으로 유니크한 값인 tag를 넣어줘야 동작(같은 값을 줘서 연결시키는 작업)
SafeArea
그 안에 있는 모든 것은 특정 공간에 있을 거라고 보장
appbar없이 페이지를 만들때 주로 사용
bottomNavigationBar
고정되어있는 footer를 만들기 위한 위젯
FractionallySizedBox
부모크기에 비례해서 크기를 정하게 해주는 위젯
withFactor을 통해 비례를 결정 Ex)1일 경우 부모와 동일한 사이즈, 0.5일 경우 부모대비 0.5배 사이즈를 가지게 된다
return FractionallySizedBox(
widthFactor: 1,
)
사용자 입력창
material design 버튼
TextButton(onPressed:(){}, child:const Text("button"))
필수값으로 duration을 받는다
text style의 에니메이션을 만들어준다
필수값으로 duration, child, style을 받는다
container의 에니메이션을 만들어준다
스크롤바와 scrollview를 같은 컨트롤러로 연결하면 스크롤바가 따라 내려온다
Scrollbar(
controller: _scrollController,
child: SingleChildScrollView(
controller: _scrollController,
움직임에 따라서 투명도를 조절하는 위젯
투토리얼에서 옆으로 스와이프 해서 넘어갈 페이지를 만들때 사용
length:3 페이지 갯수를 지정
TabBarView(children:[]) 탭할 각각의 페이지를 지정
TabPageSelector() 어떤 탭에 있는지 알려주는 바 생성
한 Widget을 다른 widget 위로 fade-in 시키는 방법
//getstureDetector 안에서 실행된다
child: AnimatedCrossFade(
crossFadeState: CrossFadeState.showSecond,
duration: Duration(microseconds: 300),
firstChild: Column(
stack내부의 element를 이동시킬 수 있게 해준다
positioned들은 stack안에서 정해진 크기가 있어야한다(positoned element들을 위한 기준점이 필요)
controller
user interaction을 받아들이고 state를 관리하는데 용이한 클래스
final TextEditingController _userController = TextEditingController();
//textfield에 컨트롤러를 줘서 사용자가 입력한 값을 받아볼수있다
TextField(
controller: _userController,
)
class _UsernameScreenState extends State<UsernameScreen> {
final TextEditingController _userController = TextEditingController();
String _username = "";
void initState() {
super.initState();
_userController.addListener(() {
setState(() {
_username = _userController.text;
});
});
}
void dispose() {
_userController.dispose();
super.dispose();
}
//ex) TextField를 제어하고 싶을때
class _UsernameScreenState extends State<UsernameScreen> {
final TextEditingController _userController = TextEditingController();
String _username = "";
void initState() {
super.initState();
_userController.addListener(() {
setState(() {
_username = _userController.text;
});
});
}
TextField(
controller: _userController,
cursorColor: Theme.of(context).primaryColor,
decoration: InputDecoration(
hintText: "Username",
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.grey.shade400,
),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.grey.shade400,
),
),
),
),
pubspec.yaml
파일에서 assets의 주석처리를 없애고 저장하고 싶은 파일이미지 경로를 기입Image.assets("assets/images/lemon.jpg")
network
외부 이미지링크를 가져올때 사용
Image.network("url이미지경로")
assetNetwork
network에서 이미지를 로딩하는 동안에는 assets폴더에 있는 로컬이미지가 보여진다
FadeInImage.assetNetwork( placeholder: 'assets/images/lemon.jpg', image: "https://source.unsplash.com/random/200x${355 + index}")
AspectRatio
특정한 비율을 따르는 위젯을 만들 수 있도록 해준다
AspectRatio(
aspectRatio: 9 / 16, //원하는 비율설정
child: FadeInImage.assetNetwork(
fit: BoxFit.fill, //사진을 어떻게 적용할지 선택