인스타그램 클론코딩

2023. 1. 3. 00:52·Flutter
728x90

 

 

GitHub - bulmang/instagram

Contribute to bulmang/instagram development by creating an account on GitHub.

github.com

앱 설명

  • 인스타그램 클론 코딩으로서 플러터 기초적인 부분을 공부했습니다.

앱 기능

  • 서버에서 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 = [ ] : 여러가지 변수를 저장해야 할 때 사용
  • 권한 요청 팝업 : 패키지 설치 필요안드로이드 폰 설정 :
    1. android폴더/gradle.properties 코드확인
    android.useAndroidX=true
    android.enableJetifier=true
    
    1. android/app/build.gradle 파일 확인
    android {
        compileSdkVersion flutter.compileSdkVersion
        ndkVersion flutter.ndkVersion
    아니면 
    		compileSdkVersion 31
    
    1. android/app/src/main/AndroidManifest.xml 파일에
    <manifest 어쩌구>
    
        <uses-permission android:name="android.permission.READ_CONTACTS"/> // 주소록 읽어오기
        <uses-permission android:name="android.permission.WRITE_CONTACTS"/> // 주소록 쓰기 추가로 권한 요청할것이 있으면 더 입력해야됨
    
       <application 어쩌구>
    
    IOS 권한 설정 :
    1. 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
    
    1. 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 만들기
    1. state에 tab의 현재상태 저장
    2. state에 따라 tab이 어떻게 보일지 작성
    3. 유저가 쉽게 state 조작할 수 있게

데이터 가져오는 법

  • GET: 데이터 읽고 싶을 때 : GET 요청 하고 싶으면 패키지 설치 필요
  1. pubspec.yaml 파일 들어가서 밑에 코드 작성
  2. dependencies: flutter: sdk: flutter https: ^0.13.4 // url 가져오기
  3. android/app/src/main/AndroidManifest.xml 파일에 들어가서 밑에 코드 작성
  4. <uses-permission android:name="android.permission.INTERNET" /> // 추가
  5. main.dart 맨 위에
  6. 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 설정 :
    1. pubspec.yaml 파일 안 코드 추가후 pub get
    2. dependencies: image_picker: ^0.8.4+4
    3. ios/Runner/Info.plist 파일 열고
    4. <key>NSPhotoLibraryUsageDescription</key> <string>사진첩좀 써도 됩니까</string> <key>NSCameraUsageDescription</key> <string>카메라좀 써도 됩니까</string> <key>NSMicrophoneUsageDescription</key> <string>마이크 권한좀 제발</string>
    5. dart 파일 맨위에 코드 추가
    6.  
  • insert : List 안에 추가 하는 함수
  • shared_preferences 설치 방법
    1. pubspec.yaml 파일에 추가하고 pub get 누르기
    2. 패키지 사용 파일 맨 위에 추가
    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 패키지 사용법
    1. 라이브러리 추가
    dependencies:
    	cashed_networ_image: ^3.1.0
    
    1. import
    import 'package:flutter/material.dart';
    
    1. 사용방법
    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 : 화면 에니메이션 기법 (다른 화면으로 전화할떄 에니메이션 효과)
    1. 같은 이미지 2개 준비
    2. 첫 번쨰 화면에 Hero 위젯 추가
    3. 두 번째 화면에 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 사용 가능 버그가 생겼을 때 버그 찾기 쉬움

  1. 패키지 설치 및 라이브러리 추가
provider: ^6.0.1 // pub get 해야함
import 'package:provider/provider.dart'; // 파일에 추가
  1. state 보관함 만들기 ( store )
class Store1 extends ChangeNotifier { 
  var name = 'Hosiu';
} // state 보관함 store
  1. store 원하는 위젯에 등록하기
ChangeNotifierProvider(
        create: (c) => Store1(),
        child: CupertinoApp(
          localizationsDelegates: [
            DefaultMaterialLocalizations.delegate,
            DefaultCupertinoLocalizations.delegate,
            DefaultWidgetsLocalizations.delegate,
          ],
            home: MyApp()
        ),// cupertinoapp 안의 모든 위젯은 Stor1안에 있던 state 사용가능
      ),
  1. 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
  • 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분정도 해맨듯.
    flatter_local_notifications 문서에서 버전 10.0에는 다음과 같은 브레이크 변경이 있습니다.
    • 밑 코드 실행
    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 = [ ] : 여러가지 변수를 저장해야 할 때 사용
  • 권한 요청 팝업 : 패키지 설치 필요안드로이드 폰 설정 :
    1. android폴더/gradle.properties 코드확인
    android.useAndroidX=true
    android.enableJetifier=true
    
    1. android/app/build.gradle 파일 확인
    android {
        compileSdkVersion flutter.compileSdkVersion
        ndkVersion flutter.ndkVersion
    아니면 
    		compileSdkVersion 31
    
    1. android/app/src/main/AndroidManifest.xml 파일에
    <manifest 어쩌구>
    
        <uses-permission android:name="android.permission.READ_CONTACTS"/> // 주소록 읽어오기
        <uses-permission android:name="android.permission.WRITE_CONTACTS"/> // 주소록 쓰기 추가로 권한 요청할것이 있으면 더 입력해야됨
    
       <application 어쩌구>
    
    IOS 권한 설정 :
    1. 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
    
    1. 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 만들기
    1. state에 tab의 현재상태 저장
    2. state에 따라 tab이 어떻게 보일지 작성
    3. 유저가 쉽게 state 조작할 수 있게

데이터 가져오는 법

  • GET: 데이터 읽고 싶을 때 : GET 요청 하고 싶으면 패키지 설치 필요
  1. pubspec.yaml 파일 들어가서 밑에 코드 작성
  2. dependencies: flutter: sdk: flutter https: ^0.13.4 // url 가져오기
  3. android/app/src/main/AndroidManifest.xml 파일에 들어가서 밑에 코드 작성
  4. <uses-permission android:name="android.permission.INTERNET" /> // 추가
  5. main.dart 맨 위에
  6. 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 설정 :
    1. pubspec.yaml 파일 안 코드 추가후 pub get
    2. dependencies: image_picker: ^0.8.4+4
    3. ios/Runner/Info.plist 파일 열고
    4. <key>NSPhotoLibraryUsageDescription</key> <string>사진첩좀 써도 됩니까</string> <key>NSCameraUsageDescription</key> <string>카메라좀 써도 됩니까</string> <key>NSMicrophoneUsageDescription</key> <string>마이크 권한좀 제발</string>
    5. dart 파일 맨위에 코드 추가
    6.  
  • insert : List 안에 추가 하는 함수
  • shared_preferences 설치 방법
    1. pubspec.yaml 파일에 추가하고 pub get 누르기
    2. 패키지 사용 파일 맨 위에 추가
    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 패키지 사용법
    1. 라이브러리 추가
    dependencies:
    	cashed_networ_image: ^3.1.0
    
    1. import
    import 'package:flutter/material.dart';
    
    1. 사용방법
    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 : 화면 에니메이션 기법 (다른 화면으로 전화할떄 에니메이션 효과)
    1. 같은 이미지 2개 준비
    2. 첫 번쨰 화면에 Hero 위젯 추가
    3. 두 번째 화면에 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 사용 가능 버그가 생겼을 때 버그 찾기 쉬움

  1. 패키지 설치 및 라이브러리 추가
provider: ^6.0.1 // pub get 해야함
import 'package:provider/provider.dart'; // 파일에 추가
  1. state 보관함 만들기 ( store )
class Store1 extends ChangeNotifier { 
  var name = 'Hosiu';
} // state 보관함 store
  1. store 원하는 위젯에 등록하기
ChangeNotifierProvider(
        create: (c) => Store1(),
        child: CupertinoApp(
          localizationsDelegates: [
            DefaultMaterialLocalizations.delegate,
            DefaultCupertinoLocalizations.delegate,
            DefaultWidgetsLocalizations.delegate,
          ],
            home: MyApp()
        ),// cupertinoapp 안의 모든 위젯은 Stor1안에 있던 state 사용가능
      ),
  1. 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
  • 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분정도 해맨듯.
    flatter_local_notifications 문서에서 버전 10.0에는 다음과 같은 브레이크 변경이 있습니다.
    • 밑 코드 실행
    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 = [ ] : 여러가지 변수를 저장해야 할 때 사용
  • 권한 요청 팝업 : 패키지 설치 필요안드로이드 폰 설정 :
    1. android폴더/gradle.properties 코드확인
    android.useAndroidX=true
    android.enableJetifier=true
    
    1. android/app/build.gradle 파일 확인
    android {
        compileSdkVersion flutter.compileSdkVersion
        ndkVersion flutter.ndkVersion
    아니면 
    		compileSdkVersion 31
    
    1. android/app/src/main/AndroidManifest.xml 파일에
    <manifest 어쩌구>
    
        <uses-permission android:name="android.permission.READ_CONTACTS"/> // 주소록 읽어오기
        <uses-permission android:name="android.permission.WRITE_CONTACTS"/> // 주소록 쓰기 추가로 권한 요청할것이 있으면 더 입력해야됨
    
       <application 어쩌구>
    
    IOS 권한 설정 :
    1. 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
    
    1. 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 만들기
    1. state에 tab의 현재상태 저장
    2. state에 따라 tab이 어떻게 보일지 작성
    3. 유저가 쉽게 state 조작할 수 있게

데이터 가져오는 법

  • GET: 데이터 읽고 싶을 때 : GET 요청 하고 싶으면 패키지 설치 필요
  1. pubspec.yaml 파일 들어가서 밑에 코드 작성
  2. dependencies: flutter: sdk: flutter https: ^0.13.4 // url 가져오기
  3. android/app/src/main/AndroidManifest.xml 파일에 들어가서 밑에 코드 작성
  4. <uses-permission android:name="android.permission.INTERNET" /> // 추가
  5. main.dart 맨 위에
  6. 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 설정 :
    1. pubspec.yaml 파일 안 코드 추가후 pub get
    2. dependencies: image_picker: ^0.8.4+4
    3. ios/Runner/Info.plist 파일 열고
    4. <key>NSPhotoLibraryUsageDescription</key> <string>사진첩좀 써도 됩니까</string> <key>NSCameraUsageDescription</key> <string>카메라좀 써도 됩니까</string> <key>NSMicrophoneUsageDescription</key> <string>마이크 권한좀 제발</string>
    5. dart 파일 맨위에 코드 추가
    6.  
  • insert : List 안에 추가 하는 함수
  • shared_preferences 설치 방법
    1. pubspec.yaml 파일에 추가하고 pub get 누르기
    2. 패키지 사용 파일 맨 위에 추가
    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 패키지 사용법
    1. 라이브러리 추가
    dependencies:
    	cashed_networ_image: ^3.1.0
    
    1. import
    import 'package:flutter/material.dart';
    
    1. 사용방법
    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 : 화면 에니메이션 기법 (다른 화면으로 전화할떄 에니메이션 효과)
    1. 같은 이미지 2개 준비
    2. 첫 번쨰 화면에 Hero 위젯 추가
    3. 두 번째 화면에 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 사용 가능 버그가 생겼을 때 버그 찾기 쉬움

  1. 패키지 설치 및 라이브러리 추가
provider: ^6.0.1 // pub get 해야함
import 'package:provider/provider.dart'; // 파일에 추가
  1. state 보관함 만들기 ( store )
class Store1 extends ChangeNotifier { 
  var name = 'Hosiu';
} // state 보관함 store
  1. store 원하는 위젯에 등록하기
ChangeNotifierProvider(
        create: (c) => Store1(),
        child: CupertinoApp(
          localizationsDelegates: [
            DefaultMaterialLocalizations.delegate,
            DefaultCupertinoLocalizations.delegate,
            DefaultWidgetsLocalizations.delegate,
          ],
            home: MyApp()
        ),// cupertinoapp 안의 모든 위젯은 Stor1안에 있던 state 사용가능
      ),
  1. 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
  • 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분정도 해맨듯.
    flatter_local_notifications 문서에서 버전 10.0에는 다음과 같은 브레이크 변경이 있습니다.
    • 밑 코드 실행
    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
'Flutter' 카테고리의 다른 글
  • [Flutter 문법]StatefulWidget parameter 넘겨주기
  • Dart 문법 정리
  • CustomErrorMessage
  • Flutter 개발 공부 정리
bulmang
bulmang
모바일 개발자 도전
  • bulmang
    bulmang
    bulmang
  • 전체
    오늘
    어제
    • 분류 전체보기 (205)
      • 알고리즘 (65)
        • List (3)
        • Two Pointer (6)
        • Binary Search (4)
        • Prefix Sum (3)
        • Sort (4)
        • Brute Force (5)
        • Array (2)
        • String (4)
        • 프로그래머스 (12)
        • 백준 (9)
        • Queue (2)
        • Stack (2)
        • Recursion (9)
      • Computer Science (16)
        • Computer Architecture (6)
        • Operating System (5)
        • Network (2)
        • 기타 (2)
        • System Programming (1)
      • Swift (70)
        • 개발 (24)
        • 정리 (25)
        • 문법 (20)
      • Flutter (24)
      • 기타 (12)
        • 후기 (12)
      • Git (6)
      • Ios 오픈소스 (5)
      • UI 디자인 (5)
      • AppleScript (2)
  • 링크

    • Notion
    • Github
  • 태그

    Java
    개발
    프로그래머스
    riverpod
    자료구조
    피플
    코딩테스트
    Xcode
    til
    today i learned
    SwiftUI
    문법
    백준
    FLUTTER
    Swift
    Apple Developer Academy
    컴퓨터구조
    IOS
    알고리즘
    협업
  • 최근 댓글

  • 최근 글

  • 인기 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.2
bulmang
인스타그램 클론코딩
상단으로

티스토리툴바