24년 6월을 기준으로 작성되었습니다.
1. go_router 패키지
Flutter에서 페이지 간 이동을 간단하고, 더 정교하게 하기 위해서 사용하는 외부 패키지이다.
https://pub.dev/packages/go_router
go_router | Flutter package
A declarative router for Flutter based on Navigation 2 supporting deep linking, data-driven routes and more
pub.dev
간단한 예제 코드이다. 자세한 go_router 사용법은 추가 학습이 필요하다.
▶️ main.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:widget_practice/screen/new_page.dart';
void main() {
runApp(MaterialApp.router(
routerConfig: GoRouter(
initialLocation: '/',
routes: [
GoRoute(
path: '/',
name: 'home',
builder: (context, _) => HomeScreen(),
),
GoRoute(
path: '/new',
name: 'new',
builder: (context, _) => NewPage(),
),
GoRoute(
path: '/new2',
name: 'new2',
builder: (context, _) => NewPage2(),
),
],
),
));
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('화면 이동하기 2'),
),
body: Center(
child: TextButton(
child: Text('Go to Page'),
onPressed: () {
context.pushNamed('new');
},
),
),
);
}
}
▶️ new_page.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class NewPage extends StatelessWidget {
const NewPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Welcome New Page!'),
),
body: Center(
child: Column(
children: [
TextButton(
child: Text('Go to Main page'),
onPressed: () {
context.pop();
},
),
TextButton(
child: Text('Go to New Page2'),
onPressed: () {
context.pushNamed('new2');
},
),
],
),
),
);
}
}
class NewPage2 extends StatelessWidget {
const NewPage2({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Welcome New Page 222!'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
TextButton(
child: Text('Go to Back'),
onPressed: () {
context.pop();
},
),
TextButton(
child: Text('Go to Home'),
onPressed: () {
context.goNamed('home');
}
),
],
),
),
);
}
}
특징은 이동하고 싶은 페이지(라우트)를 runApp 시점에 routerConfig 파라미터에 모두 등록한 다음,
기존 Navigator.push() / pop()에서 -> context() 함수들로 사용하여, 쉽게 이동할 수 있다는 점인 것 같다.
2. 라이선스 확인하기
pub.dev에서 외부 패키지를 추가할 때, 라이선스를 꼭 확인해야 한다!
➡️ 주요 라이선스
GNU GPL License와 Mozila Public License 2.0은 추가할 때 주의를 요해야 한다.
3. 3장에서만 사용하는 파일 네이밍 규칙
※ 헝가리안 명명법이라고도 하며, 현재는 IDE의 발달로 잘 사용하지 않는다고 한다!
4. timeago 패키지
https://pub.dev/packages/timeago
timeago | Dart package
A library useful for creating fuzzy timestamps. (e.g. "15 minutes ago")
pub.dev
여러 애플리케이션의 게시글이나 유튜브 동영상을 보다보면 종종 발견하는 '3초전', '10분전', '하루 전' 등등
시간 경과를 알려주는 로직을 쉽게 작성하는 외부 패키지이다.
5. Drawing based Animation 2가지 패키지
1) Rive
최근 떠오르는 애니메이션 패키지이다.
rive | Flutter package
Rive Flutter Runtime. This package provides runtime functionality for playing back and interacting with animations built with the Rive editor available at https://rive.app.
pub.dev
다른 실력자들이 Rive로 만든 다양한 애니메이션을 보고 사용할 수 있고 (저작권 주의!),
내가 직접 만들 수도 있다. Figma랑 비슷한 디자인 느낌...
Rive - Build interactive motion graphics that run anywhere
Complex designer-developer handoff is a thing of the past. Build functional graphics with motion and interactivity that run in products, apps, sites, and games.
rive.app
Rive 기반의 애니메이션은 벡터 기반의 애니메이션이기 때문에, 반드시 SizedBox()와 같은 위젯으로 감싸 크기를 지정해줘야 한다.
2) Lottie
옛날 안드로이드, iOS 개발부터 유명했던 패키지이다. 따라서 기존에 만들어진 애니메이션 예제가 많다는 장점이 있다.
※ 그러나, 최근에는 Rive가 지원하는 기능이 훨씬 많기 때문에 Rive 사용을 추천한다.
Lottie Docs
airbnb.io
6. Code based Animation 4가지 방법
난이도가 쉬운 방법부터 정렬해보자.
1) 커스텀 패키지 이용
✅ flutter_animate 패키지
https://pub.dev/packages/flutter_animate
flutter_animate | Flutter package
Add beautiful animated effects & builders in Flutter, via an easy, customizable, unified API.
pub.dev
※ app_base 프로젝트의 num_duration_extension 파일은 외부 패키지 flutter_animate의 방식을 차용했으므로, flutter_animate를 사용하려면 삭제해야 한다!
✅ animations 패키지
플러터 공식 팀에서 만든 애니메이션 패키지이다.
https://pub.dev/packages/animations
animations | Flutter package
Fancy pre-built animations that can easily be integrated into any Flutter application.
pub.dev
OpenContainer(
closedColor: Colors.transparent,
openColor: Colors.transparent,
transitionType: ContainerTransitionType.fade,
openBuilder: (BuildContext context, VoidCallback _) {
return StockDetail(stockName: e.name);
},
closedBuilder: (BuildContext context, VoidCallback action) {
return Row(
children: [
(index + 1).text.bold.white.size(16).make(),
width20,
e.name.text.bold.white.size(16).make(),
emptyExpanded,
e.todayPercentageString.text
.color(e.getTodayPercentageColor(context))
.size(16)
.make(),
],
).pSymmetric(h: 20, v: 20);
},
))
2) Implicit Animation (암시적 애니메이션)
플러터에서 공식으로 제공하는 위젯을 사용함으로써 구현한다.
1. AnimatedContainer 위젯
https://sweetburble.tistory.com/283#%E2%9C%85%20AnimatedContainer%20%EC%9C%84%EC%A0%AF-1
[코드팩토리의 플러터 프로그래밍] - 위젯 정리
24년 6월을 기준으로 작성되었습니다. 0. 기본 위젯 알아보기※ Flutter는 RichText 위젯과 Paragraph와 같은 클래스도 제공한다.https://docs.flutter.dev/ui/widgets/text Text widgetsA catalog of Flutter's widgets for display
sweetburble.tistory.com
3) Custom Implicit Animation (TweenAnimatedBuilder 예제)
이미지 파일의 색깔을 스크롤 위치에 따라 초록색에서 -> 오랜지색으로 자연스럽게 변화시키는 코드
child: TweenAnimationBuilder<Color?>(
duration: 1000.ms,
tween: ColorTween(
begin: Colors.green,
end: isTriggered ? Colors.orange : Colors.green,
),
builder: (context, value, child) => ColorFiltered(
colorFilter: ColorFilter.mode(
value ?? Colors.green,
BlendMode.modulate,
),
child: child,
),
child: Image.asset(
"$basePath/icon/map_point.png",
height: 60,
),
),
4) Explicit Animation (명시적, 커스텀 애니메이션)
AnimationController를 사용해서 커스텀 애니메이션을 직접 구현한다.
class _SettingScreenState extends State<SettingScreen> with SingleTickerProviderStateMixin {
final scrollController = ScrollController();
// 명시적 애니메이션을 위한 컨트롤러
late final animationController = AnimationController(vsync: this, duration: 2000.ms,);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
ListView(
controller: scrollController,
padding: const EdgeInsets.only(top: 150),
children: [
// 슬라이더
Obx(
() => Slider(
value: Prefs.sliderPosition.get(),
onChanged: (value) {
animationController.animateTo(value, duration: 0.ms);
Prefs.sliderPosition.set(value);
// Prefs.sliderPosition(value); -> 이 방법도 가능하다
},
),
),
BigButton(
'애니메이션 forward',
onTap: () {
animationController.forward();
},
),
BigButton(
'애니메이션 reverse',
onTap: () {
animationController.reverse();
},
),
BigButton(
'애니메이션 repeat',
onTap: () {
animationController.repeat();
},
),
BigButton(
'애니메이션 reset',
onTap: () {
animationController.reset();
},
),
],
),
AnimatedAppBar('설정', scrollController: scrollController, animationController: animationController,)
],
),
);
}
}
w_animated_app_bar.dart 에서는
class _AnimatedAppBarState extends State<AnimatedAppBar> {
final duration = 100.ms;
double scrollPosition = 0;
// Explicit Animation 구현하기
late CurvedAnimation animation = CurvedAnimation(
parent: widget.animationController, curve: Curves.bounceInOut);
@override
void initState() {
widget.animationController.addListener(() {
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
color: context.backgroundColor,
child: SafeArea(
child: Stack(
children: [
Positioned(
left: animation.value * 200, // value값이 double로 0~1 값이다
child: TweenAnimationBuilder<Color?>(
duration: 1000.ms,
tween: ColorTween(
begin: Colors.green,
end: isTriggered ? Colors.orange : Colors.green,
),
builder: (context, value, child) =>
ColorFiltered(
colorFilter: ColorFilter.mode(
value ?? Colors.green,
BlendMode.modulate,
),
child: child,
),
child: Image.asset(
"$basePath/icon/map_point.png",
height: 60,
),
),
),
],
),
),
);
}
}
7. live_background 패키지
이미 만들어 놓은 움직이는 배경화면 위젯을 사용할 수 있다.
https://pub.dev/packages/live_background
live_background | Flutter package
Provide nice moving particle bokeh effect wall paper on your background.
pub.dev
※ 개인이 시험삼아 만든 것이기 때문에, 업데이트가 더 이상 없을 확률이 높다.
8. Deprecated된 코드 정리
➡️ Part 3 -> Ch 05 -> 2. 상태 관리 없이 앱 만들어보기...
MaterialStateProperty -> WidgetStateProperty
➡️ Part 3 -> Ch 13 -> 2. easy_localization 적용
w_menu_drawer.dart 파일에서
describeEnum(currentLanguage)
을 아래와 같은 getter로 바꿔주면 된다.
currentLanguage.name
9. freezed 패키지
아마 Dart로 클래스를 생성할 때, 반복작업으로 작성해야 하는
생성자, copywith(), equals(), hashCode(), toString() 같은 메서드들을 "자동 완성"시켜주는 패키지이다.
https://github.com/rrousselGit/freezed/blob/master/resources/translations/ko_KR/README.md
freezed/resources/translations/ko_KR/README.md at master · rrousselGit/freezed
Code generation for immutable classes that has a simple syntax/API without compromising on the features. - rrousselGit/freezed
github.com
9-1. json_serializable 패키지
freezed는 대게 json_serializable 패키지도 같이 사용한다. 이 패키지도 역시 fromJson(), toJson()과 같이 json 데이터를 처리하는 데 필요한 메서드들을 "자동 완성" 시켜주는 패키지이다.
https://pub.dev/packages/json_serializable
json_serializable | Dart package
Automatically generate code for converting to and from JSON by annotating Dart classes.
pub.dev
9-2. Android Studio 플러그인 "Flutter Frezeed Snippets"
말 그대로 freezed 파일과 json 파일을 생성하기 위해 패키지가 요구하는 형식에 맞게 코드를 작성해야 하는데,
이 스니펫이 거의 다 해결해준다.
freezed / json 파일 생성 터미널 명령어는 아래와 같다.
(fvm) dart run build_runner watch (-> 지속 감시와 갱신)
(fvm) dart run build_runner build (-> 한 번만 빌드)
※ 이 명령어를 실행하기 위해서는 당연히 "build_runner" 패키지가 dev_dependencies에 추가되어 있어야 한다!
10. fl_chart 패키지
다양한 차트를 그릴 수 있는 도구를 제공하는 패키지이다.
https://pub.dev/packages/fl_chart
fl_chart | Flutter package
A highly customizable Flutter chart library that supports Line Chart, Bar Chart, Pie Chart, Scatter Chart, and Radar Chart.
pub.dev
11. 간단한 더미 이미지 제공 사이트
Lorem Picsum
Lorem Ipsum... but for photos
picsum.photos
주소 뒤에 {/가로/세로} 를 넣어서, 원하는 이미지 크기를 선택하면 되며,
결과로 {id/id값}이 붙은 사이트로 리다이렉션된다. 이 id값을 기억하면, 그 이미지를 그대로 보여준다.
빠른 로딩을 위해서는 주소를 복사할 때 캐시값까지 복사하면 된다. (그러나 시간이 지나면 캐시가 사라질 수도 있음)
https://picsum.photos/id/552/200/300
12. smooth_page_indicator 패키지
인스타 같이 어떤 포스트나 사진을 좌우로 스크롤할 때가 있다. 플러터에서는 이 형태를 "PageView" 라는 위젯으로 구현한다.
이 외부 패키지는 PageView 내부에서, 현재 어떤 페이지에 있는 지 보여주는 indicator를 쉽게 구현할 수 있도록 해준다.
https://pub.dev/packages/smooth_page_indicator
smooth_page_indicator | Flutter package
Customizable animated page indicator with a set of built-in effects.
pub.dev
13. app_settings 패키지
permission_handler 패키지가 앱의 사용권한을 제어하는데 편리하다.
하지만 사용자에게 직접 권한을 주도록 설정화면으로 보낼때는, 갤러리 권한쪽으로 밖에 보낼 수 없다.
반면 app_settings 패키지는 거의 모든 권한에 대하여, 직접 설정 화면으로 보내는 기능을 제공한다.
https://pub.dev/packages/app_settings
app_settings | Flutter package
A Flutter plugin for opening iOS and Android phone settings from an app.
pub.dev
14. nav 패키지
강의자께서 기존 플러터의 공식 nav 패키지를 래핑해서 수정한 패키지이며, 여러가지 추가 기능을 넣었다고 한다.
nav | Flutter package
Provide easy way to navigate. Includes lots of routers. You can use this library on Android & iOS.
pub.dev
14-1. nav와 go_router 패키지를 동시에 사용하는 법
나의 App에 NavigatorState를 담은 GlobalKey를 생성했을 것이다.
그 변수를 GoRouter를 생성할 때, "navigatorKey 파라미터" 에 그대로 넣어주면 된다.
class App extends StatefulWidget {
static final GlobalKey<NavigatorState> navigatorKey = GlobalKey();
const App({super.key});
@override
State<App> createState() => AppState();
}
class AppState extends State<App> with Nav, WidgetsBindingObserver {
final router = GoRouter(
navigatorKey: App.navigatorKey,
initialLocation: "/",
routes: [
GoRoute(
path: "/",
builder: (context, state) => HomeScreen(),
),
],
);
@override
GlobalKey<NavigatorState> get navigatorKey => App.navigatorKey;
}
15. auto_route 패키지
최근 부상하고 있는 라우트 패키지이다. go_route가 초반 설정이 복잡하고 귀찮았다면,
auto_route는 안드로이드 스튜디오에서 몇번의 클릭만으로 라우팅을 연결해줄 수 있다는 장점이 있다.
※ 하지만 대부분의 기업들은 go_route를 아직 사용하고 있기 때문에, 장단점을 잘 비교해서 사용해야 한다.
https://pub.dev/packages/auto_route
auto_route | Flutter package
AutoRoute is a declarative routing solution, where everything needed for navigation is automatically generated for you.
pub.dev
16. Deep Link & Firebase dynamic link 서비스 종료에 대한 대안
➡️ Deep Link 란?
딥링크는 앱의 특정 콘텐츠나 기능으로 바로 연결되는 링크이다.
일반적인 링크가 앱의 첫 화면으로 연결되는 반면, 딥링크는 사용자가 원하는 특정 페이지, 상품 정보, 이벤트 페이지 등으로 바로 이동시켜 사용자 경험을 향상시키고 전환율을 높이는 데 기여한다.
✅ 딥링크의 작동 방식
링크 클릭 : 사용자가 웹 페이지, 이메일, 광고 등에서 딥링크를 클릭한다.
-> 앱 실행 : 해당 앱이 설치되어 있다면, 딥링크는 앱을 실행하고 특정 콘텐츠로 연결한다.
-> 앱 미설치 시 : 앱이 설치되어 있지 않다면, 앱 스토어로 연결하여 앱 설치를 유도하거나 웹 페이지로 이동하여 콘텐츠를 보여줄 수 있다.
https://firebase.google.com/support/dynamic-links-faq?hl=ko
동적 링크 지원 중단 FAQ | Firebase
의견 보내기 동적 링크 지원 중단 FAQ 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 참고: Firebase 동적 링크는 지원 중단되었으므로 새 프로젝트에서 사용해
firebase.google.com
1. Airbridge
한국어 지원이 잘 되어있지만, 유료 서비스이다.
https://help.airbridge.io/ko/developers/flutter-sdk
Flutter SDK | Airbridge Help Center
airbrdige_flutter_sdk pub.dev pubspec.yaml 파일의 dependencies 블럭 안에 다음과 같은 라인을 추가해 주세요.
help.airbridge.io
2. 안드로이드의 App Link & iOS의 Universal Link
사용하기 위해서는 본인의 웹 서비스(웹 서버 + 도메인 주소)가 존재해야 한다.
-> 지속적인 운영 비용 발생!
➡️ 플러터 공식 가이드 문서
1. 안드로이드
https://docs.flutter.dev/cookbook/navigation/set-up-app-links
Set up app links for Android
How set up universal links for an iOS application built with Flutter
docs.flutter.dev
2. iOS
https://docs.flutter.dev/cookbook/navigation/set-up-universal-links
Set up universal links for iOS
How set up universal links for an iOS application built with Flutter
docs.flutter.dev
➡️ 공식 유튜브 튜토리얼
https://www.youtube.com/watch?v=6RxuDcs6jVw
17. FCM Push를 위한 firebase_messaging 연동하기
https://pub.dev/packages/firebase_messaging
firebase_messaging | Flutter package
Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS.
pub.dev
18. Localizing (다국어 처리)를 위한 "easy_localization" 패키지
https://pub.dev/packages/easy_localization
easy_localization | Flutter package
Easy and Fast internationalizing and localization your Flutter Apps, this package simplify the internationalizing process .
pub.dev
하지만 easy_localization 패키지를 사용하더라도 json 파일을 수동으로 수정하고 작성하는 것은 귀찮은 일이다!
➡️ 더 쉽고 편하게 도와주는 "sheet_loader_localization" 패키지
CSV 파일을 다운로드하고 easy_localization 및 easy_localization_loader 와 함께 작동하도록 온라인 Google 시트에서 지역화 키를 생성한다고 한다.
https://pub.dev/packages/sheet_loader_localization
sheet_loader_localization | Flutter package
Download an CSV file and generates the localization keys from an online Google Sheet.
pub.dev
'Dart와 Flutter > 15개 프로젝트' 카테고리의 다른 글
내용 정리 Part. 2 (0) | 2024.07.12 |
---|