본문 바로가기

Flutter/12 Clone 'Used Goods app'

[Flutter] Clone - 당근마켓29(InputScreen - category 구현)

이번에는 InputScreen 의 category 부분을 getx 로 구현해보겠습니다.

개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 3.0.1

 

 

 

오늘 구현한 화면은 아래와 같습니다. 카테고리 항목을 선택후 수정할때는 이전에 선택한 항목의 색상이 변경되어 있다.

 

 

 

 

파일명 변경

user_state.dart --> user_controller.dart

 

 

 

./src/states/category_controller.dart - 카테고리 관리는 getx 로 구현하였습니다.

index 를 이용하여 영문/한글 값을 찾고, 찾은 값을 이용하여 카테고리 정보는 영문 값으로 저장

 

import 'package:get/get.dart';

class CategoryController extends GetxController {
  static CategoryController get to => Get.find();

  final RxString _selectedCategoryInEng = 'none'.obs;
  String get currentCategoryInEng => _selectedCategoryInEng.value;
  String get currentCategoryInKor => categoriesMapEngToKor[_selectedCategoryInEng.value]!;

  // 키로 _selectedCategoryInEng 값 설정
  void setNewCategoryWithEng(String newCategory) {
    if (categoriesMapEngToKor.keys.contains(newCategory)) {
      _selectedCategoryInEng.value = newCategory;
    }
  }

  // 값으로 _selectedCategoryInEng 값 설정
  void setNewCategoryWithKor(String newCategory) {
    if (categoriesMapEngToKor.values.contains(newCategory)) {
      _selectedCategoryInEng.value = categoriesMapKorToEng[newCategory]!;
    }
  }
}

const Map<String, String> categoriesMapEngToKor = {
  'none': '카테고리 선택',
  'furniture': '가구',
  'electronics': '전자기기',
  'kids': '유아동',
  'sports': '스포츠',
  'woman': '여성',
  'man': '남성',
  'makeup': '메이크업',
  'desc': '아래 항목중에서 선택하세요',
};

Map<String, String> categoriesMapKorToEng =
    categoriesMapEngToKor.map((key, value) => MapEntry(value, key));

 

 

 

./src/screens/input/category_input_page.dart - CategoryController 를 화면으로 구현

 

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

import '../../states/category_controller.dart';

class CategoryInputPage extends StatelessWidget {
  const CategoryInputPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('카테고리 선택', style: Theme.of(context).textTheme.headline6),
      ),
      body: ListView.separated(
        itemBuilder: (context, index) {
          return ListTile(
            onTap: () {
              // 첫번째 항목은 선택 불가,
              if (index != 0) {
                CategoryController.to
                    .setNewCategoryWithKor(categoriesMapEngToKor.values.elementAt(index));
                debugPrint(CategoryController.to.currentCategoryInEng);
                Get.back();
              }
            },
            title: Text(
              // none 일 경우 'desc' 항목을 보여줌,
              categoriesMapEngToKor.keys.elementAt(index) == 'none'
                  ? categoriesMapEngToKor['desc']!
                  : categoriesMapEngToKor.values.elementAt(index),
              // 현재 선택된 항목을 색상 반전으로 처리,
              style: TextStyle(
                  color: (CategoryController.to.currentCategoryInKor ==
                              categoriesMapEngToKor.values.elementAt(index) &&
                          index != 0)
                      ? Theme.of(context).primaryColor
                      : Colors.black87),
            ),
          );
        },
        separatorBuilder: (context, index) {
          return Divider(height: 1, thickness: 1, color: Colors.grey[300]);
        },
        // 마지막 항목은 설명이므로 화면 출력에서 제외,
        itemCount: categoriesMapEngToKor.length - 1,
      ),
    );
  }
}

 

 

 

./src/router/locations.dart - CategoryInputPage 화면 추가 및 dependency injection

CategoryController 는 InputScreen 과 CategoryInputPage 에 필요하므로 먼저 호출되는 InputScreen 에 dependency injection 을 추가함.

 

GetPage(
  name: '/input',
  page: () => const InputScreen(),
  transition: Transition.fadeIn,
  binding: BindingsBuilder((){
    Get.put(CategoryController());
  }),
  middlewares: [CheckAuth()], // 미들웨어를 먼저 확인(로그인 여부 확인)하고 "page:" 로 이동함
),
GetPage(
  name: '/category_input',
  page: () => const CategoryInputPage(),
  transition: Transition.fadeIn,
  middlewares: [CheckAuth()], // 미들웨어를 먼저 확인(로그인 여부 확인)하고 "page:" 로 이동함
),

 

 

 

./src/screens/input/input_screen.dart - 선택된 카테고리값을 화면에 표시하기 위해서 Obx 로 wrapping 해야 함.

 

ListTile(
  onTap: () {
    debugPrint('/LOCATION_INPUT/LOCATION_CATEGORY_INPUT');
    Get.toNamed('/category_input');
  },
  dense: true,
  title: Obx((){
    return Text(CategoryController.to.currentCategoryInKor);
  }),
  trailing: const Icon(Icons.navigate_next),
),