728x90
앱 설명
- 인스타그램 클론 코딩으로서 플러터 기초적인 부분을 공부했습니다.
앱 기능
- 서버에서 json파일 가져와서 가공하여 이미지, 글 보여주기
- 사진 이미지를 눌렀을 때 Hero 에니메이션 사용하여 이동
- 작성자 눌렀을 때 프로필 페이지로 이동하여 팔로우 버튼과 사진을 Grid view, Scroll view로 가져오기
- ImagePicker 사용하여 앨범에서 사진을 선택하여 글을 작성하여 게시물 올리기
- 시간을 정하여 알람 주는 법, 알람 눌렀을 때 원하는 페이지 이동
개발 하기전 설정 사항
analysis.options.yaml안에 작성
rules:
prefer_typing_uninitialized_variables: false
prefer_const_constructors_in_immutables: false
prefer_const_constructors: false
avoid_print: false
prefer_const_literals_to_create_immutables: false
- Text(’’) : 문자
- Icon(Icons.아이콘이름) : 아이콘
- Image(’’) : assets 폴더 만든 후 이미지 저장 , pub spec.yaml 파일 가서 밑에 코드 입력
- flutter: assets: - assets/
- Center ( child : Container ( )
- Scaffold
- Scaffold( appBar: AppBar(), // 상단에 들어갈 위젯 body: Container(), // 중간에 들어갈 위젯 bottomNavigationBar: BottomAppBar( ), // 하단에 들어갈 위젯 )
- Row : 여러 위젯을 가로로 배치 Swift에서 HStack 같은 역할 Column : 여러 위젯을 세로로 배치 VStack 같은 역할
- Row( children: [ Icon(Icons.star), Icon(Icons.star), Icon(Icons.star), ], )
- crossAxisAlignment: CrossAxisAlignment.center, *// 세로축 배치*
- mainAxisAlignment: MainAxisAlignment.center, *// 가로축*
- center : 가운데 배치
- start : 왼쪽 배치
- end : 오른쪽 배치
- spaceEvently : child widget 사이의 여유 공간을 모두 균등하게 배분
- spaceBetween : child widget를 시작과 끝에 배치하고 시작과 끝 위젯의 사이에 나머지 child widget을 배치합니다. 시작과 끝 사이의 위젯의 나머지 공간은 모두 균일하게 배분합니다.
- Container : 박스 배치 하지만 SizedBox() 보다 무거움
- SizedBox : 박스 배치 width, height , child만 필요하다면 추천 , 가벼움
- margin : margin: EdgeInsets.fromLTRB(0, 12, 0, 0), 공간주는거
- BoxDecoration : 박스 모서리 색 주기
- decoration: BoxDecoration( border: Border.all(color: Colors.black) )
- stless : class생성
- ListView : ScrollView 라고 생각하면 됨. 스크롤 위치 감시도 가능함. 메모리 절약 기능이 있음.
- state : 화면을 재렌더링해준다 값이 변할때 , stful 을 쳐서 만듬
- setState : state 값을 변경하려면 사용해야한다.
- context : 부모 위젯의 정보를 담고있는 변수 , 가족 족보라고 생각하면됨.
- floatingActionButoon: 버튼
floatingActionButton: FloatingActionButton(
onPressed: (){
showDialog(context: context, builder: (context){
return Dialog(child: Text('HI'),);
});
},
),
- final : 수정안되는 변수 ( 부모가 보낸 state를 받을 때 많이 사용함)
- 부모 → 자식 한테 변수 전송하는 법 클래스에 변수명과 수 보내고 자식위젯에 등록하고 사용
DialogUI(state : a);
class DialogUI extends StatelessWidget {
const DialogUI({Key? key, this.state}) : super(key: key);
final state;
Text(state.toString())
- 자식 → 부모 한테 변수값을 변경하려면 부모위젯안에 함수를 만들어서 자식한테 전송해주면됨. setState 사용
- controller : 유저가 입력한 데이터를 변수에 저장
- TextEditingController()
- onChanged : 유저가 입력한 데이터를 변수에 저장
- Map = { } , List = [ ] : 여러가지 변수를 저장해야 할 때 사용
- 권한 요청 팝업 : 패키지 설치 필요안드로이드 폰 설정 :
- android폴더/gradle.properties 코드확인
android.useAndroidX=true android.enableJetifier=true
- android/app/build.gradle 파일 확인
android { compileSdkVersion flutter.compileSdkVersion ndkVersion flutter.ndkVersion 아니면 compileSdkVersion 31
- android/app/src/main/AndroidManifest.xml 파일에
IOS 권한 설정 :<manifest 어쩌구> <uses-permission android:name="android.permission.READ_CONTACTS"/> // 주소록 읽어오기 <uses-permission android:name="android.permission.WRITE_CONTACTS"/> // 주소록 쓰기 추가로 권한 요청할것이 있으면 더 입력해야됨 <application 어쩌구>
- iOS/Podfil에 post_install do |installer| 지우고 밑에 코드 입력 다른권한 설정 :https://pub.dev/packages/permission_handler
post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', 'PERMISSION_CONTACTS=1', #추가할거 더 있으면 이 자리에 ] end end end
- iOS/Runner/info.plist 에 밑에 코드 입력
<key>NSContactsUsageDescription</key> <string>님 폰의 연락처 권한이 필요합니다 제발 주셈</string> // 권한 달라고 팝업 띄우는 안내문
- dependencies: flutter: sdk: flutter permission_handler: ^8.3.0 main.dart 맨 위에 import 'package:permission_handler/permission_handler.dart'; 추가
- 연락처 권한 여부 확인
getPermission() async {
var status = await Permission.contacts.status; // 연락처 권한 여부
if (status.isGranted) { // 허락 했을 때
print('허락됨');
} else if (status.isDenied) { // 불허 했을 때
print('거절됨');
Permission.contacts.request(); // 팝업창이 뜸
}
}
- await : 붙으면 다음줄 실행 안하고 기다림. (Future에 사용가능)
- initState : 안에 적은 코드는 위젯 로드 될 때 한번 실행 됨.
- 동적인 UI Tab Bar 만들기
- state에 tab의 현재상태 저장
- state에 따라 tab이 어떻게 보일지 작성
- 유저가 쉽게 state 조작할 수 있게
데이터 가져오는 법
- GET: 데이터 읽고 싶을 때 : GET 요청 하고 싶으면 패키지 설치 필요
- pubspec.yaml 파일 들어가서 밑에 코드 작성
- dependencies: flutter: sdk: flutter https: ^0.13.4 // url 가져오기
- android/app/src/main/AndroidManifest.xml 파일에 들어가서 밑에 코드 작성
- <uses-permission android:name="android.permission.INTERNET" /> // 추가
- main.dart 맨 위에
- import 'package:http/http.dart' as http; import 'dart:convert';
- POST: 데이터 보내고 싶을 때
- JSON 자료
- 서버랑 주고받는 데이터는 오직 문자만 가능합니다. {}, [] 이런거 불가능 굳이 {}, [] 이걸 주고받고 싶으면 "큰따옴표"로 전부 감싸야합니다. 그럼 문자취급을 받아서 주고받을 수 있습니다. 따옴표친 {}, [] 이걸 JSON 이라고 합니다.
- Map : 여러 변수를 사용할 때 List , Map 다 안에 넣을수 있음.
- Route 만드는 법 :
- MaterialApp( initialRoute: '/', routes: { '/': (context) => Text('첫페이지'), '/detail': (context) => Text('둘째페이지'), }, );
- image_picker 설정 :
- pubspec.yaml 파일 안 코드 추가후 pub get
- dependencies: image_picker: ^0.8.4+4
- ios/Runner/Info.plist 파일 열고
- <key>NSPhotoLibraryUsageDescription</key> <string>사진첩좀 써도 됩니까</string> <key>NSCameraUsageDescription</key> <string>카메라좀 써도 됩니까</string> <key>NSMicrophoneUsageDescription</key> <string>마이크 권한좀 제발</string>
- dart 파일 맨위에 코드 추가
- insert : List 안에 추가 하는 함수
- shared_preferences 설치 방법
- pubspec.yaml 파일에 추가하고 pub get 누르기
- 패키지 사용 파일 맨 위에 추가
import 'package:shared_preferences/shared_preferences.dart'; import 'dart:convert';
- shared_preferences: ^2.0.11
- 저장공간 오픈
var storage = await SharedPreferences.getInstance();
- 자료 저장 함수들
var storage = await SharedPreferences.getInstance(); // 저장 공간 오픈
storage.setString('name','john');
storage.setBool('bool',true); //
storage.remove('name'); // 자료제거
var map = {'age' : 20};
storage.setString('map', jsonEncode(map)); // map 자료 저장하려면 json으로 바꿔서 저장해야됨.
storage.get('map');
var result = storage.getString('map') ?? ''; // 자료 출력
print(jsonDecode(result)); // 출력할 때 json자료를 map으로 변환
- cached_network_image 패키지 사용법
- 라이브러리 추가
dependencies: cashed_networ_image: ^3.1.0
- import
import 'package:flutter/material.dart';
- 사용방법
CachedNetworkImage( imageUrl: "<https://picsum.photos/250?image=5>", placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context, url, error) => Icon(Icons.error), ),
- GestureDectector : 유저가 위젯을 어떻게 터치하는지 감지
GestureDetector( child: Text(widget.data[i]['user']), onTap: (){ Navigator.push(context, MaterialPageRoute(builder: (C) => Profile()) // 텍스트를 눌렀을때 페이지가 뜬다. ); },
- onTap: (){ 한 번 누를시 실행할 코드 } onDoubleTap: (){ 더블탭시 실행할 코드 } onLongPress: (){ 길게누를시 실행할 코드 } onScaleStart: (){ 줌인시 실행할 코드 } onHorizontalDragStart: (){ 수평으로 드래그시 실행할 코드 }
- CupertinoPageRoute: 아이폰 기본 애니메이션 구현 아이폰 위젯 사용하려면 import 'package:flutter/cupertino.dart';
- 페이지 전환 커스텀 에니메이션
- PositionedTransition() : 위젯 위치 변경
- ScaleTransition() : 위젯 사이즈를 변경
- SizeTransition() : 위젯을 가렸다가 보여주기
- RotationTransition() : 위젯을 회전
SlideTransition( position: Tween( begin: Offset(-1.0, 0.0), //시작 좌표 -1은 x축, 0은 y축 end: Offset(0, 0), // 최종 좌표 ).animate(a1), )
- pageBuilder: (c,a1,a2) => Profile(), transitionsBuilder: (c,a1,a2,child) => // a1이 제일중요 = animation objcet 페이지 전환 얼마나 되었는지 0~1 부터 알려준다 페이지 전환 시작 0 중간쯤이면 0.5 다되면 1 FadeTransition(opacity: a1,child: child) // opacity 에 a1을 넣어서 fadein 효과 // 애니메이션 위젯 FadeTransition에 입력하면 된다. transitionDuration: Duration(milliseconds: 500) // 애니메이션 동작 속도 조절
- hero : 화면 에니메이션 기법 (다른 화면으로 전화할떄 에니메이션 효과)
- 같은 이미지 2개 준비
- 첫 번쨰 화면에 Hero 위젯 추가
- 두 번째 화면에 Hero 위젯 추가
GestureDetector( child: Hero( tag: 'imageHero', child: widget.data[i]['image'].runtimeType == String // runtimeType : 타입 ? Image.network(widget.data[i]['image']) : Image.file(widget.data[i]['image']), ),
child: Hero( tag: 'imageHero', child: widget.data[i]['image'].runtimeType == String // runtimeType : 타입 ? Image.network(widget.data[i]['image']) : Image.file(widget.data[i]['image']), ),
- Provider : State 보관함을 만들어서 모든 위젯이 사용 할 수 있게 만듬. state 값을 편리하게 보낼 수 있음.
Provider 장점 :
편리하게 state 사용 가능 버그가 생겼을 때 버그 찾기 쉬움
- 패키지 설치 및 라이브러리 추가
provider: ^6.0.1 // pub get 해야함
import 'package:provider/provider.dart'; // 파일에 추가
- state 보관함 만들기 ( store )
class Store1 extends ChangeNotifier {
var name = 'Hosiu';
} // state 보관함 store
- store 원하는 위젯에 등록하기
ChangeNotifierProvider(
create: (c) => Store1(),
child: CupertinoApp(
localizationsDelegates: [
DefaultMaterialLocalizations.delegate,
DefaultCupertinoLocalizations.delegate,
DefaultWidgetsLocalizations.delegate,
],
home: MyApp()
),// cupertinoapp 안의 모든 위젯은 Stor1안에 있던 state 사용가능
),
- store에 있던 state 사용 Text(context.watch<Store1>().name)
- store 안 state 값 변경 후 재랜더링 notifyListeners(); *// state 수정후 재렌더링*
- MultiProvider : Store 여러개 등록할때 사용
- MultiProvider( // Store 여러개 등록할때 사용 providers: [ ChangeNotifierProvider(create: (c) => Store1()), ChangeNotifierProvider(create: (c) => Store2()), ], )
- GridView : 격자
- GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 6), itemBuilder: (c,i){return Container(color: Colors.grey); }, itemCount: 3, )
- CustomScrollview :
- slivers : 안에 있는 것들 모두 스크롤 뷰 만들어줌
- SliverGrid() : 격자
- SliverList() : 리스트뷰
- SliverToBoxAdapter() : 박스
- SliverAppBar() : 이쁜 헤더
- pinned : true (상단고정옵션)
- floating : true (위로 스크롤시 등장여부)
- expandedHeight : 300 (높이 설정)
- 자세한 사항 : https://api.flutter.dev/flutter/material/FlexibleSpaceBar-class.html
- slivers : 안에 있는 것들 모두 스크롤 뷰 만들어줌
- CustomScrollView( slivers: [ SliverToBoxAdapter( child: ProfileHeader(), ), SliverGrid(delegate: SliverChildBuilderDelegate( (c, i) => Container(color: Colors.grey,), childCount: 23, ), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2), ) ], ),
- notification : 알림 개발환경 설정 flutter_local_notifiations: ^13.0.0 pubspe.yaml에 추가후 pub get
- 앞으로 환경 설정 할 때 패키지 버전, 플러터 버전 확인! → 플러터, 패키지 버전에 따라서 코드가 실행 안 될수 있음, 40분정도 해맨듯.
- 밑 코드 실행
import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; final notifications = FlutterLocalNotificationsPlugin(); //1. 앱로드시 실행할 기본설정 initNotification() async { //안드로이드용 아이콘파일 이름 var androidSetting = AndroidInitializationSettings('app_icon'); //ios에서 앱 로드시 유저에게 권한요청하려면 var iosSetting = IOSInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, ); var initializationSettings = InitializationSettings( android: androidSetting, iOS: iosSetting ); await notifications.initialize( initializationSettings, //알림 누를때 함수실행하고 싶으면 //onSelectNotification: 함수명추가 ); }
- IOS 설정환경 :
- ios/Runner/AppDelegate.swift 파일 밑 코드를 GeneratedPluginRegistrant.register(with: self) 코드 윗줄. 끝 iOS 버전마다 앱 알림을 관리하는 방법이 달라서 추가하는 코드
- if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate }
- AOS 설정환경 :
- android/app/src/main/res/drawable 폴더에 알림에 띄울 아이콘용 이미지를 하나 넣기
- 알림 띄워주는 코드 :
- //2. 이 함수 원하는 곳에서 실행하면 알림 뜸 showNotification() async { var androidDetails = AndroidNotificationDetails( '유니크한 알림 채널 ID', '알림종류 설명', priority: Priority.high, importance: Importance.max, color: Color.fromARGB(255, 255, 0, 0), ); var iosDetails = IOSNotificationDetails( presentAlert: true, presentBadge: true, presentSound: true, ); // 알림 id, 제목, 내용 맘대로 채우기 notifications.show( 1, '제목1', '내용1', NotificationDetails(android: androidDetails, iOS: iosDetails) ); }
- 알림 눌렀을 때 함수 실행 :
- 페이지 이동
- onSelectNotification: (payload){ Navigator.push( context, MaterialPageRoute( builder: (context) => Text('새로운 페이지'), ), ); }
- iOS 및 macOS 클래스가 그대로 변경 및 리팩터링되었습니다.동일한 운영체제를 기반으로 동일한 알림을 공유합니다.IOS 또는 MacOS 중 하나의 프레픽스를 사용하는 대신Darwin 접두사를 가진 클래스로 대체되었습니다.예를들면,IOS Initialization Settings는 Darwin으로 대체할 수 있습니다.초기화 설정
- 원하는 시간 알림 띄우기 :
- notifications.zonedSchedule : 원하는 시간에 알림 띄움
- [notifications.show](<http://notifications.show>) : 바로 알림 띄움
- tz.TZDateTime.now(tz.local) : 현재시간
- matchDateTimeComponents: DateTimeComponents.time : 매일 같은 시간에 알림 띄워줌
- 서버 알림 :
- local 알림 :
- makeDate(hour, min, sec){ var now = tz.TZDateTime.now(tz.local); var when = tz.TZDateTime(tz.local, now.year, now.month, now.day, hour, min, sec); if (when.isBefore(now)) { return when.add(Duration(days: 1)); } else { return when; } }
- 코드 추가
import 'package:timezone/data/latest_all.dart' as tz; import 'package:timezone/timezone.dart' as tz;
showNotification2() async { tz.initializeTimeZones(); var androidDetails = const AndroidNotificationDetails( '유니크한 알림 ID', '알림종류 설명', priority: Priority.high, importance: Importance.max, color: Color.fromARGB(255, 255, 0, 0), ); var iosDetails = const IOSNotificationDetails( presentAlert: true, presentBadge: true, presentSound: true, ); notifications.zonedSchedule( // show는 바로 띄우기, zonedSchedule : 원하는 시간에 알림 2, '제목2', '내용2', tz.TZDateTime.now(tz.local).add(Duration(seconds: 5)), // 시간입력하면 이시간에 띄움 5초후에 알림 띄움 NotificationDetails(android: androidDetails, iOS: iosDetails), androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime ); }
개발 하기전 설정 사항
analysis.options.yaml안에 작성
rules:
prefer_typing_uninitialized_variables: false
prefer_const_constructors_in_immutables: false
prefer_const_constructors: false
avoid_print: false
prefer_const_literals_to_create_immutables: false
- Text(’’) : 문자
- Icon(Icons.아이콘이름) : 아이콘
- Image(’’) : assets 폴더 만든 후 이미지 저장 , pub spec.yaml 파일 가서 밑에 코드 입력
- flutter: assets: - assets/
- Center ( child : Container ( )
- Scaffold
- Scaffold( appBar: AppBar(), // 상단에 들어갈 위젯 body: Container(), // 중간에 들어갈 위젯 bottomNavigationBar: BottomAppBar( ), // 하단에 들어갈 위젯 )
- Row : 여러 위젯을 가로로 배치 Swift에서 HStack 같은 역할 Column : 여러 위젯을 세로로 배치 VStack 같은 역할
- Row( children: [ Icon(Icons.star), Icon(Icons.star), Icon(Icons.star), ], )
- crossAxisAlignment: CrossAxisAlignment.center, *// 세로축 배치*
- mainAxisAlignment: MainAxisAlignment.center, *// 가로축*
- center : 가운데 배치
- start : 왼쪽 배치
- end : 오른쪽 배치
- spaceEvently : child widget 사이의 여유 공간을 모두 균등하게 배분
- spaceBetween : child widget를 시작과 끝에 배치하고 시작과 끝 위젯의 사이에 나머지 child widget을 배치합니다. 시작과 끝 사이의 위젯의 나머지 공간은 모두 균일하게 배분합니다.
- Container : 박스 배치 하지만 SizedBox() 보다 무거움
- SizedBox : 박스 배치 width, height , child만 필요하다면 추천 , 가벼움
- margin : margin: EdgeInsets.fromLTRB(0, 12, 0, 0), 공간주는거
- BoxDecoration : 박스 모서리 색 주기
- decoration: BoxDecoration( border: Border.all(color: Colors.black) )
- stless : class생성
- ListView : ScrollView 라고 생각하면 됨. 스크롤 위치 감시도 가능함. 메모리 절약 기능이 있음.
- state : 화면을 재렌더링해준다 값이 변할때 , stful 을 쳐서 만듬
- setState : state 값을 변경하려면 사용해야한다.
- context : 부모 위젯의 정보를 담고있는 변수 , 가족 족보라고 생각하면됨.
- floatingActionButoon: 버튼
floatingActionButton: FloatingActionButton(
onPressed: (){
showDialog(context: context, builder: (context){
return Dialog(child: Text('HI'),);
});
},
),
- final : 수정안되는 변수 ( 부모가 보낸 state를 받을 때 많이 사용함)
- 부모 → 자식 한테 변수 전송하는 법 클래스에 변수명과 수 보내고 자식위젯에 등록하고 사용
DialogUI(state : a);
class DialogUI extends StatelessWidget {
const DialogUI({Key? key, this.state}) : super(key: key);
final state;
Text(state.toString())
- 자식 → 부모 한테 변수값을 변경하려면 부모위젯안에 함수를 만들어서 자식한테 전송해주면됨. setState 사용
- controller : 유저가 입력한 데이터를 변수에 저장
- TextEditingController()
- onChanged : 유저가 입력한 데이터를 변수에 저장
- Map = { } , List = [ ] : 여러가지 변수를 저장해야 할 때 사용
- 권한 요청 팝업 : 패키지 설치 필요안드로이드 폰 설정 :
- android폴더/gradle.properties 코드확인
android.useAndroidX=true android.enableJetifier=true
- android/app/build.gradle 파일 확인
android { compileSdkVersion flutter.compileSdkVersion ndkVersion flutter.ndkVersion 아니면 compileSdkVersion 31
- android/app/src/main/AndroidManifest.xml 파일에
IOS 권한 설정 :<manifest 어쩌구> <uses-permission android:name="android.permission.READ_CONTACTS"/> // 주소록 읽어오기 <uses-permission android:name="android.permission.WRITE_CONTACTS"/> // 주소록 쓰기 추가로 권한 요청할것이 있으면 더 입력해야됨 <application 어쩌구>
- iOS/Podfil에 post_install do |installer| 지우고 밑에 코드 입력 다른권한 설정 :https://pub.dev/packages/permission_handler
post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', 'PERMISSION_CONTACTS=1', #추가할거 더 있으면 이 자리에 ] end end end
- iOS/Runner/info.plist 에 밑에 코드 입력
<key>NSContactsUsageDescription</key> <string>님 폰의 연락처 권한이 필요합니다 제발 주셈</string> // 권한 달라고 팝업 띄우는 안내문
- dependencies: flutter: sdk: flutter permission_handler: ^8.3.0 main.dart 맨 위에 import 'package:permission_handler/permission_handler.dart'; 추가
- 연락처 권한 여부 확인
getPermission() async {
var status = await Permission.contacts.status; // 연락처 권한 여부
if (status.isGranted) { // 허락 했을 때
print('허락됨');
} else if (status.isDenied) { // 불허 했을 때
print('거절됨');
Permission.contacts.request(); // 팝업창이 뜸
}
}
- await : 붙으면 다음줄 실행 안하고 기다림. (Future에 사용가능)
- initState : 안에 적은 코드는 위젯 로드 될 때 한번 실행 됨.
- 동적인 UI Tab Bar 만들기
- state에 tab의 현재상태 저장
- state에 따라 tab이 어떻게 보일지 작성
- 유저가 쉽게 state 조작할 수 있게
데이터 가져오는 법
- GET: 데이터 읽고 싶을 때 : GET 요청 하고 싶으면 패키지 설치 필요
- pubspec.yaml 파일 들어가서 밑에 코드 작성
- dependencies: flutter: sdk: flutter https: ^0.13.4 // url 가져오기
- android/app/src/main/AndroidManifest.xml 파일에 들어가서 밑에 코드 작성
- <uses-permission android:name="android.permission.INTERNET" /> // 추가
- main.dart 맨 위에
- import 'package:http/http.dart' as http; import 'dart:convert';
- POST: 데이터 보내고 싶을 때
- JSON 자료
- 서버랑 주고받는 데이터는 오직 문자만 가능합니다. {}, [] 이런거 불가능 굳이 {}, [] 이걸 주고받고 싶으면 "큰따옴표"로 전부 감싸야합니다. 그럼 문자취급을 받아서 주고받을 수 있습니다. 따옴표친 {}, [] 이걸 JSON 이라고 합니다.
- Map : 여러 변수를 사용할 때 List , Map 다 안에 넣을수 있음.
- Route 만드는 법 :
- MaterialApp( initialRoute: '/', routes: { '/': (context) => Text('첫페이지'), '/detail': (context) => Text('둘째페이지'), }, );
- image_picker 설정 :
- pubspec.yaml 파일 안 코드 추가후 pub get
- dependencies: image_picker: ^0.8.4+4
- ios/Runner/Info.plist 파일 열고
- <key>NSPhotoLibraryUsageDescription</key> <string>사진첩좀 써도 됩니까</string> <key>NSCameraUsageDescription</key> <string>카메라좀 써도 됩니까</string> <key>NSMicrophoneUsageDescription</key> <string>마이크 권한좀 제발</string>
- dart 파일 맨위에 코드 추가
- insert : List 안에 추가 하는 함수
- shared_preferences 설치 방법
- pubspec.yaml 파일에 추가하고 pub get 누르기
- 패키지 사용 파일 맨 위에 추가
import 'package:shared_preferences/shared_preferences.dart'; import 'dart:convert';
- shared_preferences: ^2.0.11
- 저장공간 오픈
var storage = await SharedPreferences.getInstance();
- 자료 저장 함수들
var storage = await SharedPreferences.getInstance(); // 저장 공간 오픈
storage.setString('name','john');
storage.setBool('bool',true); //
storage.remove('name'); // 자료제거
var map = {'age' : 20};
storage.setString('map', jsonEncode(map)); // map 자료 저장하려면 json으로 바꿔서 저장해야됨.
storage.get('map');
var result = storage.getString('map') ?? ''; // 자료 출력
print(jsonDecode(result)); // 출력할 때 json자료를 map으로 변환
- cached_network_image 패키지 사용법
- 라이브러리 추가
dependencies: cashed_networ_image: ^3.1.0
- import
import 'package:flutter/material.dart';
- 사용방법
CachedNetworkImage( imageUrl: "<https://picsum.photos/250?image=5>", placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context, url, error) => Icon(Icons.error), ),
- GestureDectector : 유저가 위젯을 어떻게 터치하는지 감지
GestureDetector( child: Text(widget.data[i]['user']), onTap: (){ Navigator.push(context, MaterialPageRoute(builder: (C) => Profile()) // 텍스트를 눌렀을때 페이지가 뜬다. ); },
- onTap: (){ 한 번 누를시 실행할 코드 } onDoubleTap: (){ 더블탭시 실행할 코드 } onLongPress: (){ 길게누를시 실행할 코드 } onScaleStart: (){ 줌인시 실행할 코드 } onHorizontalDragStart: (){ 수평으로 드래그시 실행할 코드 }
- CupertinoPageRoute: 아이폰 기본 애니메이션 구현 아이폰 위젯 사용하려면 import 'package:flutter/cupertino.dart';
- 페이지 전환 커스텀 에니메이션
- PositionedTransition() : 위젯 위치 변경
- ScaleTransition() : 위젯 사이즈를 변경
- SizeTransition() : 위젯을 가렸다가 보여주기
- RotationTransition() : 위젯을 회전
SlideTransition( position: Tween( begin: Offset(-1.0, 0.0), //시작 좌표 -1은 x축, 0은 y축 end: Offset(0, 0), // 최종 좌표 ).animate(a1), )
- pageBuilder: (c,a1,a2) => Profile(), transitionsBuilder: (c,a1,a2,child) => // a1이 제일중요 = animation objcet 페이지 전환 얼마나 되었는지 0~1 부터 알려준다 페이지 전환 시작 0 중간쯤이면 0.5 다되면 1 FadeTransition(opacity: a1,child: child) // opacity 에 a1을 넣어서 fadein 효과 // 애니메이션 위젯 FadeTransition에 입력하면 된다. transitionDuration: Duration(milliseconds: 500) // 애니메이션 동작 속도 조절
- hero : 화면 에니메이션 기법 (다른 화면으로 전화할떄 에니메이션 효과)
- 같은 이미지 2개 준비
- 첫 번쨰 화면에 Hero 위젯 추가
- 두 번째 화면에 Hero 위젯 추가
GestureDetector( child: Hero( tag: 'imageHero', child: widget.data[i]['image'].runtimeType == String // runtimeType : 타입 ? Image.network(widget.data[i]['image']) : Image.file(widget.data[i]['image']), ),
child: Hero( tag: 'imageHero', child: widget.data[i]['image'].runtimeType == String // runtimeType : 타입 ? Image.network(widget.data[i]['image']) : Image.file(widget.data[i]['image']), ),
- Provider : State 보관함을 만들어서 모든 위젯이 사용 할 수 있게 만듬. state 값을 편리하게 보낼 수 있음.
Provider 장점 :
편리하게 state 사용 가능 버그가 생겼을 때 버그 찾기 쉬움
- 패키지 설치 및 라이브러리 추가
provider: ^6.0.1 // pub get 해야함
import 'package:provider/provider.dart'; // 파일에 추가
- state 보관함 만들기 ( store )
class Store1 extends ChangeNotifier {
var name = 'Hosiu';
} // state 보관함 store
- store 원하는 위젯에 등록하기
ChangeNotifierProvider(
create: (c) => Store1(),
child: CupertinoApp(
localizationsDelegates: [
DefaultMaterialLocalizations.delegate,
DefaultCupertinoLocalizations.delegate,
DefaultWidgetsLocalizations.delegate,
],
home: MyApp()
),// cupertinoapp 안의 모든 위젯은 Stor1안에 있던 state 사용가능
),
- store에 있던 state 사용 Text(context.watch<Store1>().name)
- store 안 state 값 변경 후 재랜더링 notifyListeners(); *// state 수정후 재렌더링*
- MultiProvider : Store 여러개 등록할때 사용
- MultiProvider( // Store 여러개 등록할때 사용 providers: [ ChangeNotifierProvider(create: (c) => Store1()), ChangeNotifierProvider(create: (c) => Store2()), ], )
- GridView : 격자
- GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 6), itemBuilder: (c,i){return Container(color: Colors.grey); }, itemCount: 3, )
- CustomScrollview :
- slivers : 안에 있는 것들 모두 스크롤 뷰 만들어줌
- SliverGrid() : 격자
- SliverList() : 리스트뷰
- SliverToBoxAdapter() : 박스
- SliverAppBar() : 이쁜 헤더
- pinned : true (상단고정옵션)
- floating : true (위로 스크롤시 등장여부)
- expandedHeight : 300 (높이 설정)
- 자세한 사항 : https://api.flutter.dev/flutter/material/FlexibleSpaceBar-class.html
- slivers : 안에 있는 것들 모두 스크롤 뷰 만들어줌
- CustomScrollView( slivers: [ SliverToBoxAdapter( child: ProfileHeader(), ), SliverGrid(delegate: SliverChildBuilderDelegate( (c, i) => Container(color: Colors.grey,), childCount: 23, ), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2), ) ], ),
- notification : 알림 개발환경 설정 flutter_local_notifiations: ^13.0.0 pubspe.yaml에 추가후 pub get
- 앞으로 환경 설정 할 때 패키지 버전, 플러터 버전 확인! → 플러터, 패키지 버전에 따라서 코드가 실행 안 될수 있음, 40분정도 해맨듯.
- 밑 코드 실행
import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; final notifications = FlutterLocalNotificationsPlugin(); //1. 앱로드시 실행할 기본설정 initNotification() async { //안드로이드용 아이콘파일 이름 var androidSetting = AndroidInitializationSettings('app_icon'); //ios에서 앱 로드시 유저에게 권한요청하려면 var iosSetting = IOSInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, ); var initializationSettings = InitializationSettings( android: androidSetting, iOS: iosSetting ); await notifications.initialize( initializationSettings, //알림 누를때 함수실행하고 싶으면 //onSelectNotification: 함수명추가 ); }
- IOS 설정환경 :
- ios/Runner/AppDelegate.swift 파일 밑 코드를 GeneratedPluginRegistrant.register(with: self) 코드 윗줄. 끝 iOS 버전마다 앱 알림을 관리하는 방법이 달라서 추가하는 코드
- if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate }
- AOS 설정환경 :
- android/app/src/main/res/drawable 폴더에 알림에 띄울 아이콘용 이미지를 하나 넣기
- 알림 띄워주는 코드 :
- //2. 이 함수 원하는 곳에서 실행하면 알림 뜸 showNotification() async { var androidDetails = AndroidNotificationDetails( '유니크한 알림 채널 ID', '알림종류 설명', priority: Priority.high, importance: Importance.max, color: Color.fromARGB(255, 255, 0, 0), ); var iosDetails = IOSNotificationDetails( presentAlert: true, presentBadge: true, presentSound: true, ); // 알림 id, 제목, 내용 맘대로 채우기 notifications.show( 1, '제목1', '내용1', NotificationDetails(android: androidDetails, iOS: iosDetails) ); }
- 알림 눌렀을 때 함수 실행 :
- 페이지 이동
- onSelectNotification: (payload){ Navigator.push( context, MaterialPageRoute( builder: (context) => Text('새로운 페이지'), ), ); }
- iOS 및 macOS 클래스가 그대로 변경 및 리팩터링되었습니다.동일한 운영체제를 기반으로 동일한 알림을 공유합니다.IOS 또는 MacOS 중 하나의 프레픽스를 사용하는 대신Darwin 접두사를 가진 클래스로 대체되었습니다.예를들면,IOS Initialization Settings는 Darwin으로 대체할 수 있습니다.초기화 설정
- 원하는 시간 알림 띄우기 :
- notifications.zonedSchedule : 원하는 시간에 알림 띄움
- [notifications.show](<http://notifications.show>) : 바로 알림 띄움
- tz.TZDateTime.now(tz.local) : 현재시간
- matchDateTimeComponents: DateTimeComponents.time : 매일 같은 시간에 알림 띄워줌
- 서버 알림 :
- local 알림 :
- makeDate(hour, min, sec){ var now = tz.TZDateTime.now(tz.local); var when = tz.TZDateTime(tz.local, now.year, now.month, now.day, hour, min, sec); if (when.isBefore(now)) { return when.add(Duration(days: 1)); } else { return when; } }
- 코드 추가
import 'package:timezone/data/latest_all.dart' as tz; import 'package:timezone/timezone.dart' as tz;
showNotification2() async { tz.initializeTimeZones(); var androidDetails = const AndroidNotificationDetails( '유니크한 알림 ID', '알림종류 설명', priority: Priority.high, importance: Importance.max, color: Color.fromARGB(255, 255, 0, 0), ); var iosDetails = const IOSNotificationDetails( presentAlert: true, presentBadge: true, presentSound: true, ); notifications.zonedSchedule( // show는 바로 띄우기, zonedSchedule : 원하는 시간에 알림 2, '제목2', '내용2', tz.TZDateTime.now(tz.local).add(Duration(seconds: 5)), // 시간입력하면 이시간에 띄움 5초후에 알림 띄움 NotificationDetails(android: androidDetails, iOS: iosDetails), androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime ); }
개발 하기전 설정 사항
analysis.options.yaml안에 작성
rules:
prefer_typing_uninitialized_variables: false
prefer_const_constructors_in_immutables: false
prefer_const_constructors: false
avoid_print: false
prefer_const_literals_to_create_immutables: false
- Text(’’) : 문자
- Icon(Icons.아이콘이름) : 아이콘
- Image(’’) : assets 폴더 만든 후 이미지 저장 , pub spec.yaml 파일 가서 밑에 코드 입력
- flutter: assets: - assets/
- Center ( child : Container ( )
- Scaffold
- Scaffold( appBar: AppBar(), // 상단에 들어갈 위젯 body: Container(), // 중간에 들어갈 위젯 bottomNavigationBar: BottomAppBar( ), // 하단에 들어갈 위젯 )
- Row : 여러 위젯을 가로로 배치 Swift에서 HStack 같은 역할 Column : 여러 위젯을 세로로 배치 VStack 같은 역할
- Row( children: [ Icon(Icons.star), Icon(Icons.star), Icon(Icons.star), ], )
- crossAxisAlignment: CrossAxisAlignment.center, *// 세로축 배치*
- mainAxisAlignment: MainAxisAlignment.center, *// 가로축*
- center : 가운데 배치
- start : 왼쪽 배치
- end : 오른쪽 배치
- spaceEvently : child widget 사이의 여유 공간을 모두 균등하게 배분
- spaceBetween : child widget를 시작과 끝에 배치하고 시작과 끝 위젯의 사이에 나머지 child widget을 배치합니다. 시작과 끝 사이의 위젯의 나머지 공간은 모두 균일하게 배분합니다.
- Container : 박스 배치 하지만 SizedBox() 보다 무거움
- SizedBox : 박스 배치 width, height , child만 필요하다면 추천 , 가벼움
- margin : margin: EdgeInsets.fromLTRB(0, 12, 0, 0), 공간주는거
- BoxDecoration : 박스 모서리 색 주기
- decoration: BoxDecoration( border: Border.all(color: Colors.black) )
- stless : class생성
- ListView : ScrollView 라고 생각하면 됨. 스크롤 위치 감시도 가능함. 메모리 절약 기능이 있음.
- state : 화면을 재렌더링해준다 값이 변할때 , stful 을 쳐서 만듬
- setState : state 값을 변경하려면 사용해야한다.
- context : 부모 위젯의 정보를 담고있는 변수 , 가족 족보라고 생각하면됨.
- floatingActionButoon: 버튼
floatingActionButton: FloatingActionButton(
onPressed: (){
showDialog(context: context, builder: (context){
return Dialog(child: Text('HI'),);
});
},
),
- final : 수정안되는 변수 ( 부모가 보낸 state를 받을 때 많이 사용함)
- 부모 → 자식 한테 변수 전송하는 법 클래스에 변수명과 수 보내고 자식위젯에 등록하고 사용
DialogUI(state : a);
class DialogUI extends StatelessWidget {
const DialogUI({Key? key, this.state}) : super(key: key);
final state;
Text(state.toString())
- 자식 → 부모 한테 변수값을 변경하려면 부모위젯안에 함수를 만들어서 자식한테 전송해주면됨. setState 사용
- controller : 유저가 입력한 데이터를 변수에 저장
- TextEditingController()
- onChanged : 유저가 입력한 데이터를 변수에 저장
- Map = { } , List = [ ] : 여러가지 변수를 저장해야 할 때 사용
- 권한 요청 팝업 : 패키지 설치 필요안드로이드 폰 설정 :
- android폴더/gradle.properties 코드확인
android.useAndroidX=true android.enableJetifier=true
- android/app/build.gradle 파일 확인
android { compileSdkVersion flutter.compileSdkVersion ndkVersion flutter.ndkVersion 아니면 compileSdkVersion 31
- android/app/src/main/AndroidManifest.xml 파일에
IOS 권한 설정 :<manifest 어쩌구> <uses-permission android:name="android.permission.READ_CONTACTS"/> // 주소록 읽어오기 <uses-permission android:name="android.permission.WRITE_CONTACTS"/> // 주소록 쓰기 추가로 권한 요청할것이 있으면 더 입력해야됨 <application 어쩌구>
- iOS/Podfil에 post_install do |installer| 지우고 밑에 코드 입력 다른권한 설정 :https://pub.dev/packages/permission_handler
post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', 'PERMISSION_CONTACTS=1', #추가할거 더 있으면 이 자리에 ] end end end
- iOS/Runner/info.plist 에 밑에 코드 입력
<key>NSContactsUsageDescription</key> <string>님 폰의 연락처 권한이 필요합니다 제발 주셈</string> // 권한 달라고 팝업 띄우는 안내문
- dependencies: flutter: sdk: flutter permission_handler: ^8.3.0 main.dart 맨 위에 import 'package:permission_handler/permission_handler.dart'; 추가
- 연락처 권한 여부 확인
getPermission() async {
var status = await Permission.contacts.status; // 연락처 권한 여부
if (status.isGranted) { // 허락 했을 때
print('허락됨');
} else if (status.isDenied) { // 불허 했을 때
print('거절됨');
Permission.contacts.request(); // 팝업창이 뜸
}
}
- await : 붙으면 다음줄 실행 안하고 기다림. (Future에 사용가능)
- initState : 안에 적은 코드는 위젯 로드 될 때 한번 실행 됨.
- 동적인 UI Tab Bar 만들기
- state에 tab의 현재상태 저장
- state에 따라 tab이 어떻게 보일지 작성
- 유저가 쉽게 state 조작할 수 있게
데이터 가져오는 법
- GET: 데이터 읽고 싶을 때 : GET 요청 하고 싶으면 패키지 설치 필요
- pubspec.yaml 파일 들어가서 밑에 코드 작성
- dependencies: flutter: sdk: flutter https: ^0.13.4 // url 가져오기
- android/app/src/main/AndroidManifest.xml 파일에 들어가서 밑에 코드 작성
- <uses-permission android:name="android.permission.INTERNET" /> // 추가
- main.dart 맨 위에
- import 'package:http/http.dart' as http; import 'dart:convert';
- POST: 데이터 보내고 싶을 때
- JSON 자료
- 서버랑 주고받는 데이터는 오직 문자만 가능합니다. {}, [] 이런거 불가능 굳이 {}, [] 이걸 주고받고 싶으면 "큰따옴표"로 전부 감싸야합니다. 그럼 문자취급을 받아서 주고받을 수 있습니다. 따옴표친 {}, [] 이걸 JSON 이라고 합니다.
- Map : 여러 변수를 사용할 때 List , Map 다 안에 넣을수 있음.
- Route 만드는 법 :
- MaterialApp( initialRoute: '/', routes: { '/': (context) => Text('첫페이지'), '/detail': (context) => Text('둘째페이지'), }, );
- image_picker 설정 :
- pubspec.yaml 파일 안 코드 추가후 pub get
- dependencies: image_picker: ^0.8.4+4
- ios/Runner/Info.plist 파일 열고
- <key>NSPhotoLibraryUsageDescription</key> <string>사진첩좀 써도 됩니까</string> <key>NSCameraUsageDescription</key> <string>카메라좀 써도 됩니까</string> <key>NSMicrophoneUsageDescription</key> <string>마이크 권한좀 제발</string>
- dart 파일 맨위에 코드 추가
- insert : List 안에 추가 하는 함수
- shared_preferences 설치 방법
- pubspec.yaml 파일에 추가하고 pub get 누르기
- 패키지 사용 파일 맨 위에 추가
import 'package:shared_preferences/shared_preferences.dart'; import 'dart:convert';
- shared_preferences: ^2.0.11
- 저장공간 오픈
var storage = await SharedPreferences.getInstance();
- 자료 저장 함수들
var storage = await SharedPreferences.getInstance(); // 저장 공간 오픈
storage.setString('name','john');
storage.setBool('bool',true); //
storage.remove('name'); // 자료제거
var map = {'age' : 20};
storage.setString('map', jsonEncode(map)); // map 자료 저장하려면 json으로 바꿔서 저장해야됨.
storage.get('map');
var result = storage.getString('map') ?? ''; // 자료 출력
print(jsonDecode(result)); // 출력할 때 json자료를 map으로 변환
- cached_network_image 패키지 사용법
- 라이브러리 추가
dependencies: cashed_networ_image: ^3.1.0
- import
import 'package:flutter/material.dart';
- 사용방법
CachedNetworkImage( imageUrl: "<https://picsum.photos/250?image=5>", placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context, url, error) => Icon(Icons.error), ),
- GestureDectector : 유저가 위젯을 어떻게 터치하는지 감지
GestureDetector( child: Text(widget.data[i]['user']), onTap: (){ Navigator.push(context, MaterialPageRoute(builder: (C) => Profile()) // 텍스트를 눌렀을때 페이지가 뜬다. ); },
- onTap: (){ 한 번 누를시 실행할 코드 } onDoubleTap: (){ 더블탭시 실행할 코드 } onLongPress: (){ 길게누를시 실행할 코드 } onScaleStart: (){ 줌인시 실행할 코드 } onHorizontalDragStart: (){ 수평으로 드래그시 실행할 코드 }
- CupertinoPageRoute: 아이폰 기본 애니메이션 구현 아이폰 위젯 사용하려면 import 'package:flutter/cupertino.dart';
- 페이지 전환 커스텀 에니메이션
- PositionedTransition() : 위젯 위치 변경
- ScaleTransition() : 위젯 사이즈를 변경
- SizeTransition() : 위젯을 가렸다가 보여주기
- RotationTransition() : 위젯을 회전
SlideTransition( position: Tween( begin: Offset(-1.0, 0.0), //시작 좌표 -1은 x축, 0은 y축 end: Offset(0, 0), // 최종 좌표 ).animate(a1), )
- pageBuilder: (c,a1,a2) => Profile(), transitionsBuilder: (c,a1,a2,child) => // a1이 제일중요 = animation objcet 페이지 전환 얼마나 되었는지 0~1 부터 알려준다 페이지 전환 시작 0 중간쯤이면 0.5 다되면 1 FadeTransition(opacity: a1,child: child) // opacity 에 a1을 넣어서 fadein 효과 // 애니메이션 위젯 FadeTransition에 입력하면 된다. transitionDuration: Duration(milliseconds: 500) // 애니메이션 동작 속도 조절
- hero : 화면 에니메이션 기법 (다른 화면으로 전화할떄 에니메이션 효과)
- 같은 이미지 2개 준비
- 첫 번쨰 화면에 Hero 위젯 추가
- 두 번째 화면에 Hero 위젯 추가
GestureDetector( child: Hero( tag: 'imageHero', child: widget.data[i]['image'].runtimeType == String // runtimeType : 타입 ? Image.network(widget.data[i]['image']) : Image.file(widget.data[i]['image']), ),
child: Hero( tag: 'imageHero', child: widget.data[i]['image'].runtimeType == String // runtimeType : 타입 ? Image.network(widget.data[i]['image']) : Image.file(widget.data[i]['image']), ),
- Provider : State 보관함을 만들어서 모든 위젯이 사용 할 수 있게 만듬. state 값을 편리하게 보낼 수 있음.
Provider 장점 :
편리하게 state 사용 가능 버그가 생겼을 때 버그 찾기 쉬움
- 패키지 설치 및 라이브러리 추가
provider: ^6.0.1 // pub get 해야함
import 'package:provider/provider.dart'; // 파일에 추가
- state 보관함 만들기 ( store )
class Store1 extends ChangeNotifier {
var name = 'Hosiu';
} // state 보관함 store
- store 원하는 위젯에 등록하기
ChangeNotifierProvider(
create: (c) => Store1(),
child: CupertinoApp(
localizationsDelegates: [
DefaultMaterialLocalizations.delegate,
DefaultCupertinoLocalizations.delegate,
DefaultWidgetsLocalizations.delegate,
],
home: MyApp()
),// cupertinoapp 안의 모든 위젯은 Stor1안에 있던 state 사용가능
),
- store에 있던 state 사용 Text(context.watch<Store1>().name)
- store 안 state 값 변경 후 재랜더링 notifyListeners(); *// state 수정후 재렌더링*
- MultiProvider : Store 여러개 등록할때 사용
- MultiProvider( // Store 여러개 등록할때 사용 providers: [ ChangeNotifierProvider(create: (c) => Store1()), ChangeNotifierProvider(create: (c) => Store2()), ], )
- GridView : 격자
- GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 6), itemBuilder: (c,i){return Container(color: Colors.grey); }, itemCount: 3, )
- CustomScrollview :
- slivers : 안에 있는 것들 모두 스크롤 뷰 만들어줌
- SliverGrid() : 격자
- SliverList() : 리스트뷰
- SliverToBoxAdapter() : 박스
- SliverAppBar() : 이쁜 헤더
- pinned : true (상단고정옵션)
- floating : true (위로 스크롤시 등장여부)
- expandedHeight : 300 (높이 설정)
- 자세한 사항 : https://api.flutter.dev/flutter/material/FlexibleSpaceBar-class.html
- slivers : 안에 있는 것들 모두 스크롤 뷰 만들어줌
- CustomScrollView( slivers: [ SliverToBoxAdapter( child: ProfileHeader(), ), SliverGrid(delegate: SliverChildBuilderDelegate( (c, i) => Container(color: Colors.grey,), childCount: 23, ), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2), ) ], ),
- notification : 알림 개발환경 설정 flutter_local_notifiations: ^13.0.0 pubspe.yaml에 추가후 pub get
- 앞으로 환경 설정 할 때 패키지 버전, 플러터 버전 확인! → 플러터, 패키지 버전에 따라서 코드가 실행 안 될수 있음, 40분정도 해맨듯.
- 밑 코드 실행
import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; final notifications = FlutterLocalNotificationsPlugin(); //1. 앱로드시 실행할 기본설정 initNotification() async { //안드로이드용 아이콘파일 이름 var androidSetting = AndroidInitializationSettings('app_icon'); //ios에서 앱 로드시 유저에게 권한요청하려면 var iosSetting = IOSInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, ); var initializationSettings = InitializationSettings( android: androidSetting, iOS: iosSetting ); await notifications.initialize( initializationSettings, //알림 누를때 함수실행하고 싶으면 //onSelectNotification: 함수명추가 ); }
- IOS 설정환경 :
- ios/Runner/AppDelegate.swift 파일 밑 코드를 GeneratedPluginRegistrant.register(with: self) 코드 윗줄. 끝 iOS 버전마다 앱 알림을 관리하는 방법이 달라서 추가하는 코드
- if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate }
- AOS 설정환경 :
- android/app/src/main/res/drawable 폴더에 알림에 띄울 아이콘용 이미지를 하나 넣기
- 알림 띄워주는 코드 :
- //2. 이 함수 원하는 곳에서 실행하면 알림 뜸 showNotification() async { var androidDetails = AndroidNotificationDetails( '유니크한 알림 채널 ID', '알림종류 설명', priority: Priority.high, importance: Importance.max, color: Color.fromARGB(255, 255, 0, 0), ); var iosDetails = IOSNotificationDetails( presentAlert: true, presentBadge: true, presentSound: true, ); // 알림 id, 제목, 내용 맘대로 채우기 notifications.show( 1, '제목1', '내용1', NotificationDetails(android: androidDetails, iOS: iosDetails) ); }
- 알림 눌렀을 때 함수 실행 :
- 페이지 이동
- onSelectNotification: (payload){ Navigator.push( context, MaterialPageRoute( builder: (context) => Text('새로운 페이지'), ), ); }
- iOS 및 macOS 클래스가 그대로 변경 및 리팩터링되었습니다.동일한 운영체제를 기반으로 동일한 알림을 공유합니다.IOS 또는 MacOS 중 하나의 프레픽스를 사용하는 대신Darwin 접두사를 가진 클래스로 대체되었습니다.예를들면,IOS Initialization Settings는 Darwin으로 대체할 수 있습니다.초기화 설정
- 원하는 시간 알림 띄우기 :
- notifications.zonedSchedule : 원하는 시간에 알림 띄움
- [notifications.show](<http://notifications.show>) : 바로 알림 띄움
- tz.TZDateTime.now(tz.local) : 현재시간
- matchDateTimeComponents: DateTimeComponents.time : 매일 같은 시간에 알림 띄워줌
- 서버 알림 :
- local 알림 :
- makeDate(hour, min, sec){ var now = tz.TZDateTime.now(tz.local); var when = tz.TZDateTime(tz.local, now.year, now.month, now.day, hour, min, sec); if (when.isBefore(now)) { return when.add(Duration(days: 1)); } else { return when; } }
- 코드 추가
import 'package:timezone/data/latest_all.dart' as tz; import 'package:timezone/timezone.dart' as tz;
showNotification2() async { tz.initializeTimeZones(); var androidDetails = const AndroidNotificationDetails( '유니크한 알림 ID', '알림종류 설명', priority: Priority.high, importance: Importance.max, color: Color.fromARGB(255, 255, 0, 0), ); var iosDetails = const IOSNotificationDetails( presentAlert: true, presentBadge: true, presentSound: true, ); notifications.zonedSchedule( // show는 바로 띄우기, zonedSchedule : 원하는 시간에 알림 2, '제목2', '내용2', tz.TZDateTime.now(tz.local).add(Duration(seconds: 5)), // 시간입력하면 이시간에 띄움 5초후에 알림 띄움 NotificationDetails(android: androidDetails, iOS: iosDetails), androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime ); }
728x90
'Flutter' 카테고리의 다른 글
[피플] - 이슈 수정 (git, 협업능력) (0) | 2023.02.03 |
---|---|
[Flutter 문법]StatefulWidget parameter 넘겨주기 (0) | 2023.01.20 |
Dart 문법 정리 (0) | 2023.01.04 |
CustomErrorMessage (0) | 2023.01.03 |
Flutter 개발 공부 정리 (0) | 2023.01.02 |