카테고리 없음

29일차 Getx

신승호. 2023. 3. 9. 18:31
  1. Getx 패키지를 활용하여 기본적으로 제공되는 다음의 Get의 메서드를 활용하고 실행결과를 포함하여 내용을 정리하시오.   

Get.dialog : dialog 띄워주는 방법이며, 기존 showDialog 와 같은 역할을 합니다.

  main.dart

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:myapp29/page/main_page.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      home: MainPage(),
    );
  }
}

lib/page/main_page.dart

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:get/get.dart';

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: TextButton(
          onPressed: () {
            Get.dialog(AlertDialog(
              title: Text('나 dialog title'),
              content: Text('나 dialog content'),
              actions: [
                TextButton(onPressed: Get.back, child: Text('취소')),
                TextButton(onPressed: Get.back, child: Text('확인'))
              ],
            ));
          },
          child: const Text('dialog 나와'),
        ),
      ),
    );
  }
}

결과

  • Get.dialog 에 들어가는 속성은 다음과 같다.
Future<T?> dialog<T>(

  // dialog 내부 위젯
  Widget widget, {
  
  // dialog 외부 클릭 시 dismiss 여부
  bool barrierDismissible = true,
  
  // dialog 외부 색상 
  Color? barrierColor,
  
  // safeArea 준수
  bool useSafeArea = true,
  
  // key 설정
  GlobalKey<NavigatorState>? navigatorKey,
  
  // 
  Object? arguments,
  
  // dialog 가 열고 닫힐 때 애니메이션 시간 설정
  Duration? transitionDuration,
  
  // dialog 가 열고 닫힐 애니메이션
  Curve? transitionCurve,
  
  // dialog 이름 설정 - 로그에 표시 됩니다.
  String? name,
  
  // 라우트 설정
  RouteSettings? routeSettings,
})

Get.bottomSheet 

  - main.dart

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:myapp29/page/main_page.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      home: MainPage(),
    );
  }
}

  - lib/page/main_page.dart

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:get/get.dart';

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: TextButton(
          onPressed: () {
            Get.bottomSheet(Container(
              height: 200,
              decoration: BoxDecoration(color: Colors.white),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    '나 bottomSheet',
                    style: TextStyle(fontSize: 20),
                  ),
                  ElevatedButton(onPressed: Get.back, child: Text('닫기'))
                ],
              ),
            ));
          },
          child: const Text('bottomSheet 나와'),
        ),
      ),
    );
  }
}

bottomSheet  결과

 

  • Get.bottomSheet 에 들어가는 속성은 다음과 같습니다.
Future<T?> bottomSheet<T>(
  
  // bottom sheet 에 들어갈 위젯
  Widget bottomsheet, {
  
  // bottom sheet 의 배경색
  Color? backgroundColor,
  
  // 그림자 굵기
  double? elevation,
  
  // 지속성 여부
  bool persistent = true,
  
  // 테두리 모양 
  ShapeBorder? shape,
  
  // clip 설정
  Clip? clipBehavior,
  
  // bottom sheet 외부 색상
  Color? barrierColor,
  
  // SafeArea 지킬지 여부
  bool? ignoreSafeArea,
  
  // 스크롤 가능 여부
  bool isScrollControlled = false,
  
  // useRootNavigator 사용 여부
  bool useRootNavigator = false,
  
  // bottom sheet 외부 클릭 시 pop 여부
  bool isDismissible = true,
  
  // bottom sheet drag 가능 여부
  bool enableDrag = true,
  
  // route 설정
  RouteSettings? settings,
  
  // bottom sheet 가 열릴 때 속도
  Duration? enterBottomSheetDuration,
  
   // bottom sheet 가 닫힐 때 속도
  Duration? exitBottomSheetDuration,
})

 

Get.snackbar

  - main.dart

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:myapp29/page/main_page.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      home: MainPage(),
    );
  }
}

  - lib/page/main_page.dart

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:get/get.dart';

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: TextButton(
          onPressed: () {
            Get.snackbar(
              'snackbar title',
              'snackbar content',
              colorText: Colors.white,
              backgroundColor: Colors.black,
            );
          },
          child: const Text('snackbar 나와'),
        ),
      ),
    );
  }
}

  • Get.sanckbar 에 들어가는 속성은 다음과 같습니다.
SnackbarController snackbar(

  // snackBar title 문자열
  String title,
  
  // snackBar message 문자열
  String message,
  
  // title, message color
  Color? colorText,
  
  // snackBar 노출 시간
  Duration? duration = const Duration(seconds: 3),

  // snackBar 위치 - SnackPosition.TOP, SnackPosition.BOTTOM
  SnackPosition? snackPosition,
  
  // title 부분 위젯 titleText 를 넣었다면 title 은 무시됩니다.
  Widget? titleText,
  
  // message 부분 위젯 messageText 를 넣었다면 message 는 무시됩니다.
  Widget? messageText,
  
  // snackBar 왼쪽 부분의 icon
  Widget? icon,
  
  // icon 의 깜빡거림 여부를 결정합니다.
  bool? shouldIconPulse,
  
  // snackBar 의 최대 width 를 정합니다.
  double? maxWidth,
  
  // snackBar margin 설정
  EdgeInsets? margin,
  
  // snackBar padding 설정
  EdgeInsets? padding,
  
  // snackBar radius 설정
  double? borderRadius,
  
  // snackBar 테두리 색상 설정
  Color? borderColor,
  
  // snackBar 테두리 굵기 설정
  double? borderWidth,
  
  // snackBar 색상 설정
  Color? backgroundColor,
  
  // snackBar
  Color? leftBarIndicatorColor,
  
  // snackBar BoxShadow 설정
  List<BoxShadow>? boxShadows,
  
  // snackBar 배경 Gradient 설정
  Gradient? backgroundGradient,
  
  // snackBar 우측 TextButton
  TextButton? mainButton,
  
  // snackBar click event
  OnTap? onTap,
  
  // 수동 dismiss 여부
  bool? isDismissible,
  
  // dismiss 방향 설정
  DismissDirection? dismissDirection,
  
  // snackBar 상단 progress 노출 여부
  bool? showProgressIndicator,
  
  // snackBar 상단 progress controller 설정
  AnimationController? progressIndicatorController,
  
  // snackBar 상단 progress 배경색 설정
  Color? progressIndicatorBackgroundColor,
  
  // snackBar 상단 progress 색상 설정
  Animation<Color>? progressIndicatorValueColor,
  
  // snackBar style 설정
  SnackStyle? snackStyle,
  
  // snackBar 가 나타날 때 애니메이션
  Curve? forwardAnimationCurve,
  
  // snackBar 가 꺼질 때 애니메이션
  Curve? reverseAnimationCurve,
  
  // 애니메이션 시간
  Duration? animationDuration,
  
  // snackBar 
  double? barBlur,
  
  // snackBar 가 떠있을 때 외부 blur 처리
  double? overlayBlur,
  
  // snackBar 외부 색상
  Color? overlayColor,
  
  // snackBar 상태를 리턴하는 함수 - OPEN, CLOSED, OPENING, CLOSING
  SnackbarStatusCallback? snackbarStatus,
  
  // 왜 있는지는 모르겠지만 ... snackBar 하단의 Form 위젯 
  Form? userInputForm,
})

 

 

 

 

 

2.  i18n이 무엇을 의미하는지 알아내고, Getx 패키지에서 이를 구현하는 방법에 대해 정리하시오.

  i18n은 Internationalization의 축약형이다.

국제화, Internationalization는 알파벳이 20개인데 , 가장 첫 글자인 i와 가장 마지막 글자인 n 사이에 알파벳이 18개가 있다고 해서 i18n이라 칭한다.

 국제화는 다양한 언어 및 지역에 적용할 수 있도록 프로그램을 설계하는 프로세스다. 이상적으로는 국제화는 설계의 기본 단계 중 하나이다.

프로그램이 특정 지역이나 언어에 종속되지 않고 다양한 지역, 언어에서 정상 작동하도록 국제적으로 통용되는 sw을 설계하고 개발하는 과정을 말한다.

 

Getx 패키지에서 이를 구현하는 방법은

1. 파일에 종속성으로 get을 추가하여 시작한다 pubspec.yaml. pub 에서 그에 따라 최신 버전을 확인한다.

2. GetX를 사용하여 다국어 지원 기능을 사용하기 위해서는 Translations을 상속받은 클래스를 생성할 필요가 있다.

lib/model/language.dart

import 'package:get/get.dart';

class Languages extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
        'ko_KR': {
          'hello': '안녕하세요',
        },
        'ja_JP': {
          'hello': 'こんにちは',
        },
        'en_US': {
          'hello': 'Hello',
        },
      };
}

3. 다음으로 최상위 수준 위젯이 MaterialApp 대신 GetMaterialApp 인지 확인한다 .

4. 생성한 Translations 클래스를 GetX가 사용하도록 설정한다.

return GetMaterialApp(
      .....
      translations: Languages(),
      .....
);

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

lib/model/language.dart는 위에 있음(클래스 생성)

main.dart

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:myapp29/model/language.dart';
import 'package:myapp29/page/main_page.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      translations: Languages(), // 생성한 Translations 클래스를 GetMaterialApp에 설정
      locale:
          Locale('ja', 'JP'),
      fallbackLocale: Locale('en', 'US'),
      //하지만, 모든 언어를 지원하지 않으므로, 지원하지 않은 언어를 사용하는 곳에서 기본적으로 표시될 언어를 fallbackLocale 옵션에 설정
      home: MainPage(),
    );
  }
}

lib/page/main_page.dart

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:get/get.dart';

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text('hello'.tr),
          ElevatedButton(
              onPressed: () => Get.updateLocale(const Locale('ko', 'KR')),
              child: Text('Korean'))
        ],
      )),
    );
  }
}

 

 

 

 

 

 

 

3. GetxController를 활용하여 다음의 정보를 포함하고있는 “전역”컨트롤러를 만드시오

  • 컨트롤러명은 다음과 같다.
    • AppSettingController
  • 포함되어야 하는 멤버변수는 다음과 같다.bool isSoundOn 
    bool isNotificationOn
    String appVersion
    String appName
    String appAuthor
    String appPackageName
    DateTime? lastUpdated
  • 위 데이터를 메인페이지에서 Get.put하여 전역에서 사용할 수 있도록 등록하고, 최소 두 페이지 이상에 Get.find하여 해당 데이터를 불러올 수 있도록 하시오.
  • 페이지 명, 페이지 수는 상관없으며 임의로 존재하는 페이지로 한다. 이 때 페이지들은 서로 네비게이션을 다음과 같이 할 수 있도록 한다.
Get.to(()=>페이지명());

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

lib/model/appsettingcontroller.dart

import 'package:get/get.dart';

class AppSettingController extends GetxController {
  bool isSoundOn;
  bool isNotificationOn;
  String appVersion;
  String appName;
  String appAuthor;
  String appPackageName;
  DateTime? lastUpdated;

  AppSettingController({
    required this.isSoundOn,
    required this.isNotificationOn,
    required this.appVersion,
    required this.appName,
    required this.appAuthor,
    required this.appPackageName,
    required this.lastUpdated,
  });
}

lib/page/main_page.dart

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:myapp29/model/appsettingcontroller.dart';
import 'package:myapp29/page/information_page.dart';
import 'package:myapp29/page/setting_page.dart';

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    Get.put(AppSettingController(
        isSoundOn: true,
        isNotificationOn: true,
        appVersion: 'v2',
        appName: 'appName',
        appAuthor: 'appAuthor',
        appPackageName: 'appPackageName',
        lastUpdated: DateTime.now()));
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
                onPressed: (() => Get.to(() => SettingPage())),
                child: Text('App Setting')),
            ElevatedButton(
                onPressed: (() => Get.to(() => InformationPage())),
                child: Text('App Information'))
          ],
        ),
      ),
    );
  }
}

lib/page/setting_page.dart

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:get/get.dart';
import 'package:myapp29/model/appsettingcontroller.dart';

class SettingPage extends StatefulWidget {
  const SettingPage({super.key});

  @override
  State<SettingPage> createState() => _SettingPageState();
}

class _SettingPageState extends State<SettingPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Setting'),
            Row(
              children: [
                Checkbox(
                    value: Get.find<AppSettingController>().isSoundOn,
                    onChanged: ((value) {})),
                Text('Sound')
              ],
            ),
            Row(
              children: [
                Checkbox(
                    value: Get.find<AppSettingController>().isNotificationOn,
                    onChanged: ((value) {})),
                Text('Notification')
              ],
            )
          ],
        ),
      ),
    );
  }
}

lib/page/information_page.dart

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:myapp29/model/appsettingcontroller.dart';

class InformationPage extends StatefulWidget {
  const InformationPage({super.key});

  @override
  State<InformationPage> createState() => _InformationPageState();
}

class _InformationPageState extends State<InformationPage> {
  @override
  Widget build(BuildContext context) {
    var controller = Get.find<AppSettingController>();
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('App Information',
                style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)),
            Text(controller.appVersion),
            Text(controller.appName),
            Text(controller.appAuthor),
            Text(controller.appPackageName),
            Text(controller.lastUpdated.toString())
          ],
        ),
      ),
    );
  }
}

결과

[참고]

https://dalgoodori.tistory.com/57

https://dev-yakuza.posstree.com/ko/flutter/getx/localization/