- Flutter 2.0
- 모바일 개발 환경 발전사
- Flutter 설치
- 지원 가능한 배포 환경
- Window에 설치
- MacBook에 설치
- VSCode에서 사용 설정
- Project 실행
- 개발 환경 구성
- Flutter Project 생성
- Folder 구조
- Application 구조
- Widget
- flutter/material.dart
- flutter/cupertino.dart
- BLoC
- JSON
- 유용한 코드
- 프로그램 샘플
- 참고 문헌
Flutter 2.0
홈페이지 : https://flutter.dev/
Dart
홈페이지 : https://dart.dev/
매뉴얼 : https://dart.dev/guides
테스트 환경 : DartPad
Dart와 Flutter의 웹 테스트 환경
Fuchsai에서 동작하는 크로스 플랫폼 프레임워크
Cross platform 모바일, 웹, 데스크톱 UI SDK이다. 하나의 코드로 안드로이드, 아이폰, 맥북, 윈도우즈 pc, 웹용 앱을 만들 수 있다!
Dart를 사용한다.
네이티스 CPU 머신 코드로 직접 컴파일을 지원한다.
UI를 자체 렌더 엔진 스키아로 렌더링하여 성능이 뛰어나다.
구글의 Material 테마 디자인과 Ripple 애니메이션을 사용가능하다.
반대로 안드로이드에서 애플의 Cupertino 테마를 적용가능하다. ~~~와웅~~~
각 OS 플랫폼의 네이티브 UI 구성 요소로 변환하지 않고, 플러터의 그래픽 렌더 엔진을 통해 직접 플랫폼 Canvas상에 드로잉하기 때문에 높은 성능과 플랫폼 무관한 디자인을 구현가능하다.
React native에 비해 관심을 더 쏟고 있다는 것이 장점
모바일 개발 환경 발전사
Kotlin
Web View, Web App
React Native : JavaScript 사용
Flutter
Flutter 설치
지원 가능한 배포 환경
android
ios
web
window
linux
Window에 설치
Git 2.27
Flutter 3.22.2
Dart 3.4.3
DevTools 2.34.3
VSCode 1.90.2
Android
Android Studio 2024.1.1
#--- Flutter 설치
#--- FLUTTER_HOME="c:/appl/flutter"
# https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_3.22.2-stable.zip
flutter --version
dart --version
#--- Flutter 설치 확인
flutter upgrade
flutter doctor
flutter doctor -v #--- 오류 확인시
flutter doctor --android-licenses
flutter pub upgrade #--- 설치 모듈 업그레이드
# dart fix
#--- Android Studio 설치
# https://developer.android.com/studio?hl=ko
MacBook에 설치
Git 2.42.0
Flutter 3.22.2
Dart 3.4.3
VSCode 1.90.2
Android
Android Studio 2024.1.1
iOS
Xcode 15.4
Rosetta 2
CocoaPods 1.15.2
ffi 1.15.5
iOS Simulator 17.5
#--- Rosetta 2 설치
# softwareupdate --install-rosetta --agree-to-license
#--- Flutter 설치
#--- FLUTTER_HOME="/Users/ghkim/appl/flutter"
FLUTTER_DOWNLOAD="https://storage.googleapis.com/flutter_infra_release/releases"
FLUTTER_FILENAME="flutter_macos_arm64_3.22.2-stable"
cd /Users/ghkim/work/zztemp
wget ${FLUTTER_DOWNLOAD}/stable/macos/${FLUTTER_FILENAME}.zip
unzip ${${FLUTTER_FILENAME}}.zip -d /Users/ghkim/appl
flutter --version
dart --version
sudo gem install cocoapods
sudo gem pristine ffi --version 1.15.5
#--- Flutter 설치 확인
flutter upgrade
flutter doctor
flutter doctor -v #--- 오류 확인시
flutter doctor --android-licenses
flutter pub upgrade #--- 설치 모듈 업그레이드
# dart fix
#--- iOS Simulator 설치
xcodebuild -downloadPlatform iOS
# Xcode 실행
# "Window > Devices and Simulators > Simulators" 메뉴
# 좌측의 Simulators에서 "+" 버튼을 눌러 추가 한다.
open -a Simulator
# Simulator App 실행
# "File > Open Simulator> 메뉴에서 원하는 iOS device 선택
# "Settings app > General > About" 메뉴
#--- Android Studio 설치
# https://developer.android.com/studio?utm_source=android-studio&hl=ko
VSCode에서 사용 설정
Extensions
Flutter 3.90.0 (dartcode.org)
Dart 3.90.0 (dartcode.org)
Project 생성
"보기 > 명령 팔레트 ..." 메뉴에서 "FlutterL New Project" 선택
"Application" 선택
work 폴더 선택
Project Name : obcon_mobile
Project 실행
"보기 > 명령 팔레트 ..." 메뉴에서 "Flutter: Select Device" 선택
실행할 device를 선택 한다.
"실행 > 디버깅 시작" 메뉴(F5)를 선택 한다.
Debug Console view를 모니터링 한다.
실행 중 변경된 코드를 바로 반영하고 싶은 경우 "Hot Reload" 버튼을 선택 한다.
"보기 > 명령 팔레트 ..." 메뉴에서 "Flutter: Launch Emulator" 실행
"Pixel 4 XL" 선택
"실행 또는 디버그" 아이콘을 선택하여 앱 실행
Project 실행
"보기 > 명령 팔레트 ..." 메뉴에서 "Flutter: Select Device" 선택
실행할 device를 선택 한다.
"실행 > 디버깅 시작" 메뉴(F5)를 선택 한다.
Debug Console view를 모니터링 한다.
실행 중 변경된 코드를 바로 반영하고 싶은 경우 "Hot Reload" 버튼을 선택 한다.
개발 환경 구성
MacBook에서 obcon_mobile project 생성
Window에서 obcon_mobile project 생성
obcon_mobile을 obcon_mobile_windows로 이름 변경
MacBook의 obcon_mobile로 git repository 생성
Window에서 obcon_mobile을 clone
동기화를 위해 obcon_mobile_windows에서 obcon_mobile로 다음을 복사
.dart_tool/
.idea/
obcon_mobile.iml
Flutter Project 생성
Android Studio 프로그램을 실행 한다.
"New Flutter Project" 버튼을 선택 한다.
Flutter SDK path : c:/appl/flutter252
Project name : obcon_mobile
Project locatin : c:/work/OBCon_Mobile
Project type : Application
Organization : biz.obcon.flutter
Android language : Kotlin
iOS language : Swift
Platform : Android, iOS
Folder 구조
.dart_tool/ : Dart Tool 설정 폴더
.idea/ : VSC (Visual Studio Code) 설정 폴더
android/ : Android 코드 생성용 폴더
assets/ : 자원 폴더
build/ : 컴파일과 빌드용 폴더
ios/ : iOS 코드 생성용 폴더
lib/ : 프로그램 소스 코드
include/
modules/
homes/
users/
main.dart : 어플리케이션의 메인 프로그램
OBConApp.dart
test/ : 테스트 프로그램 소스 코드
upgrades/ : 업그레이드 관리용으로 만든 폴더
zzstudy/ : 스터리용으로 만든 폴더
pubspec.yaml : 어플리케이션 설정
pubspec.lock
.flutter-plugins
.flutter-plugins-dependencies
.metadata
.packages : 패키지 정의
analysis_options.yaml
obcon_mobile.iml
Application 구조
MyApp
MyHomePage
State : _MyHomePageState
build() : 화면을 구성
Widget
flutter/material.dart
안드로이드용 테마 적용
구조
MaterialApp (Stateful)
Scaffold (Stateful)
AppBar (Stateful)
SliverAppBar
SliverFillRemaining
SliverList
body
BottomNavigationBar
BottomNavigationBarItem
BottomSheet
FloatingActionButton (Stateless) : 플로팅 버튼
Drawer : 드로우 메뉴
화면
StatelessWidget
StatefulWidget
createState() : 상태 객체 생성
State
widget 변수로 StatefulWidget 참조
initState() : 초기화
didChangeDependencies()
initState() 함수 뒤에 호출됨
build() : 화면 생성
setState() : 상태 업데이트
이후 didUpdateWidget() > build() > updateShouldNotify() > didUpdateWidget() 함수가 호출됨
didUpdateWidget()
InheritedWidget에 의존하고 있는 경우에만 호출됨
dispose() : 삭제
InheritedWidget : 하위 위젯에서 접속할 수 있는 위젯
사례 : Theme, MediaQuery, Scaffold
updateShouldNotify()
.of(context).문법 사용
레이아웃
Container : 하나의 위젯을 포함
Row : 수평 방향 정렬
Column : 수직 방향 정렬
Stack : 여러 위젯을 겹쳐서 표시
Table
TableColumnWidth
TableCellVerticalAlignment
TableRow
TableCell
모양과 정렬
Center
Padding
Align : 정렬
Expanded : 위젯의 높이를 비율로 지정
SizedBoz : 위젯의 크기를 지정
Card : 카드 형태의 위젯
기초
ListView (Stateless) < CustomScrollView
ListTitle (Stateless) : 항목
AboutListTitle
StreamBuilder : 비동기 데이터로 위젯을 만들어 반환
SingleChildScrollView : 상하 스크롤 구현
Column
ListBody
Divider
GridView : 여러 열을 표시
SliverGrid
SliverChildBuilderDelegate
SliverGridDelegateWithEixedCrossAxisCount
PageView : 좌우로 슬라이드하는 페이지
DefaultTabController
TabBar
Tab
TabBarView
출력
Text (Stateless)
Image (Stateful)
assets/image/
pubspec.yaml
Icon (Stateless)
CicleAvatar (Stateless)
Opacity : 투명도 부여
버튼
RaisedButton (Stateless)
FlatButton
DropdownButton
IconButton
FloatingActionButton (Stateless)
입력
Form
TextFormField (Stateful)
DropdownButtonFormField
CountryDropdownField
FormField
checkbox
FormState
save()
reset()
validate()
GlobalKey
TextField
InputDecoration
CheckBox
Switch
Radio
RadioListTitle
AlertDialog
DatePicker
TimePicker
이벤트
GestureDetector : Widget에 제스처 기능을 추가
Dismissible
InkWell
RouteObserver
NavigatorObserver
RouteAware
BuildTransitions
SlideTransition
SizeTransition
RotationTransition
AlignTransition
기타
애니메이션
Hero (Stateful)
AnimatedContainer
AnimationController
CustomPainter
Paint
flutter/cupertino.dart
iOS용 테마 적용
CupertinoNavigationBar
CupertinoSwitch
CupertinoButton
CupertinoAlertDialog
CupertinoPicker
BLoC
Business Logic Component
StreamController와 ~.of(context) 기능을 사용하여 구현함
~.stream.listen()
~.add()
StreamController.broadcast()
StreamBuilder 사용
JSON
import 'package:json_annotation/json_annotation.dart';
// part 'todo.g.dart';
@JsonSerializable()
class Todo {
final field01;
Todo(this.field01);
factory Todo.fromJson(Map json) => _$TodoFromJson(json);
Map toJson => _$TodoToJson(this);
}
import 'dart:convert';
String context = '{ ~ }';
Map jsonObj = json.decode();
jsonObj = Map{
'name01': 'value01',
'name01': 100
};
context = json.encode(jsonObj);
유용한 코드
//--- aaa 위젯의 상위 위젯중에서 ppp를 가진 위젯의 ppp를 반환 한다.
aaa.of(context).ppp
//--- StreamController
//--- StreamController.broadcast() : 전체 전파
StreamController _controller = StreamController();
Stream get onEvent => _controller.stream;
//--- Listen하고 있다가 실행할 함수 지정
onEvent.listen((NewEvent event) => print(event));
//--- Event 호출
_controller.add(NewEvent());
//--- Future
Future funcFuture() async {
try {
return true;
} catch (err) {
print('Error: $err')
return false;
}
}
funcFuture()
.then((bool returnValue) => {})
.catchError((err) => {});
bool returnValue = await funcFuture();
//--- 일정 시간 후에 함수 실행
Timer(const Duration(seconds: 2), () => goHomePage(context));
Future.delayed(2 * 1000).then(() => goHomePage(context));
//--- 화면 넓이 반환
final width = MediaQuery.of(context).size.width;
프로그램 샘플
import 'package:flutter/material.dart';
void main() => runApp(OBConApp());
class OBConApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'OBCon Mobile',
theme: ThemeData(
primarySwatch: Colors.blue
),
home: OBConHomePage(title: '홈페이지')
);
}
}
class OBConHomePage extends StatefulWidget {
final String title;
OBConHomePage({Key: key, this.title}) : super(key: key);
State createState() => _OBConState();
}
class _OBConState extends State {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
}
@override
void setState(VoidCallback fn) {
}
}
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('~'),
Text(
'~',
style: TextStyle(
color: Colors.black,
fontSize: 20.0, //--- dp
background: Paint()
..color = Color(0xFFDCEDC8)
..style = PaintingStyle.fill,
fontWeight: FontWeight.bold
)
)
Image.asset('assets/~.jpg')
]
)