[Flutter] 연습하기 4 - Flutter Shopping Cart app

2025. 1. 14. 12:27·Flutter/App
728x90
디자인 시안 

 

쇼핑카트 앱 만들기: 단계별 구현

Flutter를 사용해 쇼핑카트 앱을 만드는 과정입니다. 이 앱에서는 기본적인 UI 설계와 기능 구현을 단계별로 진행합니다.

 

1. 기본 코드 설계

앱의 구조는 기본적으로 StatefulWidget과 StatelessWidget을 이용하여 UI를 구성합니다. 기본 코드에서 MaterialApp을 설정하고, ShoppingCartPage라는 페이지를 메인으로 설정합니다.

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: mTheme(),
      home: ShoppingCartPage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}

 

2. Constants 및 Theme 설정

앱의 기본적인 색상 및 테마는 constants.dart와 theme.dart 파일을 통해 관리합니다. 테마를 설정해 앱의 일관성을 유지합니다.

constants.dart

import 'package:flutter/material.dart';

const kPrimaryColor = MaterialColor(
  0xFFeeeeee,
  <int, Color>{
    50: Color(0xFFeeeeee),
    100: Color(0xFFeeeeee),
    200: Color(0xFFeeeeee),
    300: Color(0xFFeeeeee),
    400: Color(0xFFeeeeee),
    500: Color(0xFFeeeeee),
    600: Color(0xFFeeeeee),
    700: Color(0xFFeeeeee),
    800: Color(0xFFeeeeee),
    900: Color(0xFFeeeeee),
  },
);

const kSecondaryColor = Color(0xFFc6c6c6); // 기본 버튼 색
const kAccentColor = Color(0xFFff7643); // 활성화 버튼 색

 

theme.dart

import 'package:flutter/material.dart';
import 'package:shopping_cart_app/constants.dart';

ThemeData mTheme() {
  return ThemeData(
    primarySwatch: kPrimaryColor,
    scaffoldBackgroundColor: kPrimaryColor,
  );
}

3. 쇼핑카트 헤더 만들기

ShoppingcartHeader는 쇼핑카트 앱의 헤더 부분을 담당하는 위젯입니다. 이미지를 선택할 수 있는 기능을 추가하여, 사용자가 다양한 카테고리(예: 자전거, 비행기 등)를 선택할 수 있게 합니다.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shopping_cart_app/constants.dart';

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

  @override
  State<ShoppingcartHeader> createState() => _ShoppingcartHeaderState();
}

class _ShoppingcartHeaderState extends State<ShoppingcartHeader> {
  // 1. 상태
  int selectedId = 0;
  List<String> selectPic = [
    'assets/p1.jpeg',
    'assets/p2.jpeg',
    'assets/p3.jpeg',
    'assets/p4.jpeg',
  ];

  // 상태는 행위를 통해서 변경해야 한다.
  void changeSelectedId(int sId) {
    setState(() {
      selectedId = sId;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 이미지를 항상 5 : 3 비율로 유지하기 위해 설정
        Padding(
          padding: const EdgeInsets.all(16.0),
          child: AspectRatio(
            aspectRatio: 5 / 3,
            child: Image.asset(
              selectPic[selectedId],
              fit: BoxFit.cover,
            ),
          ),
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            _buildHeaderSelectorButton(0, Icons.directions_bike),
            _buildHeaderSelectorButton(1, Icons.motorcycle),
            _buildHeaderSelectorButton(2, CupertinoIcons.car_detailed),
            _buildHeaderSelectorButton(3, CupertinoIcons.airplane),
          ],
        )
      ],
    );
  }

  Widget _buildHeaderSelectorButton(int sId, IconData mIcon) {
    return Container(
      width: 70,
      height: 70,
      decoration: BoxDecoration(
        color: (selectedId == sId) ? kAccentColor : kSecondaryColor,
        borderRadius: BorderRadius.circular(20.0),
      ),
      child: IconButton(
        onPressed: () {
          changeSelectedId(sId);
        },
        icon: Icon(
          mIcon,
          color: Colors.black,
        ),
      ),
    );
  }
} // end of header 위젯

4. Main AppBar 추가

쇼핑카트 페이지에 AppBar를 추가하여 네비게이션 기능을 구현합니다. 뒤로 가기 버튼과 장바구니 아이콘을 포함하여 사용자가 편리하게 앱을 탐색할 수 있도록 합니다.

import 'package:flutter/material.dart';
import 'package:shopping_cart_app/components/shoppingcart_header.dart';
import 'package:shopping_cart_app/theme.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: mTheme(),
      home: ShoppingCartPage(),
    );
  }
}

// 여기는 페이지
class ShoppingCartPage extends StatelessWidget {
  const ShoppingCartPage({super.key});

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: _buildShoppingCartAppBar(),
        body: Column(
          children: [
            ShoppingcartHeader(),
            // 디테일
          ],
        ),
      ),
    );
  }

  AppBar _buildShoppingCartAppBar() {
    return AppBar(
      leading: IconButton(
        onPressed: () {},
        icon: Icon(Icons.arrow_back),
      ),
      actions: [
        IconButton(
          onPressed: () {},
          icon: Icon(Icons.shopping_cart),
        )
      ],
    );
  }
} // end of page

5. 쇼핑카트 바디 만들기

쇼핑카트의 본문에는 상품 이름, 가격, 별점, 리뷰, 색상 선택 등의 정보가 포함됩니다. 현재는 Placeholder() 위젯을 사용하여 구현 예정인 UI 영역을 표시하고 있습니다.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shopping_cart_app/constants.dart';

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

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Padding(
        padding: const EdgeInsets.only(top: 50.0),
        child: Container(
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.all(Radius.circular(30.0)),
          ),

          // 임시 ListView 사용
          child: Column(
            children: [
              _buildBodyNameAndPrice(),
              _buildBodyRatingAndReviewCount(),
              _buildBodyColorOptions(),
              _buildBodyButton(context),
            ],
          ),
        ),
      ),
    );
  } // end of build

  // 1. 이름과 가격
  Widget _buildBodyNameAndPrice() {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(
            'Urban Soft AL 10.0',
            style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
          ),
          Text(
            '\$699',
            style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
          ),
        ],
      ),
    );
  }

  // 2. 별점 리뷰 카운트
  Widget _buildBodyRatingAndReviewCount() {
    return Padding(
      padding: const EdgeInsets.only(left: 16.0, right: 16.0),
      child: Row(
        children: [
          Icon(Icons.star, color: Colors.yellow),
          Icon(Icons.star, color: Colors.yellow),
          Icon(Icons.star, color: Colors.yellow),
          Icon(Icons.star, color: Colors.yellow),
          Icon(Icons.star, color: Colors.yellow),
          Spacer(),
          Text(
            'review',
            style: TextStyle(fontSize: 15),
          ),
          Text(
            '(26)',
            style: TextStyle(fontSize: 15, color: Colors.blue),
          )
        ],
      ),
    );
  }

  // 3. 색상 옵션 선택
  Widget _buildBodyColorOptions() {
    return Padding(
      padding: const EdgeInsets.only(bottom: 20, left: 20, top: 20),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('Color Options'),
          SizedBox(height: 30),
          Row(
            children: [
              _buildColorOption(Colors.black),
              _buildColorOption(Colors.green),
              _buildColorOption(Colors.orange),
              _buildColorOption(Colors.grey),
              _buildColorOption(Colors.white),
            ],
          )
        ],
      ),
    );
  }

  // 4. 색상 옵션 위젯을 만드는 함수
  Widget _buildColorOption(Color mColor) {
    return Padding(
      padding: EdgeInsets.only(right: 10),
      child: Stack(
        children: [
          Container(
            width: 50,
            height: 50,
            decoration: BoxDecoration(
              color: Colors.white,
              border: Border.all(),
              shape: BoxShape.circle,
            ),
          ),
          // Positioned 위젯 활용
          Positioned(
            left: 5,
            top: 5,
            child: ClipOval(
              child: Container(
                color: mColor,
                width: 40,
                height: 40,
              ),
            ),
          ),
          SizedBox(height: 80),
        ],
      ),
    );
  }

// 5. 버튼 만들기
  Widget _buildBodyButton(BuildContext context) {
    return Align(
      child: TextButton(
        onPressed: () {
          // Add to Cart 버튼을 눌렀을 때 CupertinoAlertDialog를 띄우는 코드
          showCupertinoDialog(
            context: context,
            builder: (context) => CupertinoAlertDialog(
              title: Text('장바구니에 담으시겠습니까?'),
              actions: [
                CupertinoDialogAction(
                  child: Text('확인'),
                  onPressed: () {
                    Navigator.pop(context);
                  },
                ),
              ],
            ),
          );
        },
        style: TextButton.styleFrom(
          backgroundColor: kAccentColor,
          minimumSize: Size(300, 50),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(20),
          ),
        ),
        child: Text(
          'Add to Cart',
          style: TextStyle(
            color: Colors.white,
            fontSize: 25,
          ),
        ),
      ),
    );
  }
}

▼쇼핑카트 앱 완성 화면

결론

이 단계별 구현을 통해 쇼핑카트 앱을 점진적으로 구축할 수 있습니다. 각 부분은 유기적으로 연결되어 있으며, 추후 실제 데이터와 상호작용을 추가하여 더욱 완성도 있는 쇼핑카트 앱을 만들 수 있습니다.

'Flutter > App' 카테고리의 다른 글

[Flutter] 상태 관리 앱 만들기 (StatefulWidget 사용)  (1) 2025.02.03
[Flutter] 상태 관리 앱 만들기 (stl, stf)  (1) 2025.02.03
[Flutter] 연습하기 4 - Flutter Login app  (0) 2025.01.13
[Flutter] Flutter Scroll Wiget  (2) 2025.01.08
[Flutter] 연습하기 3 - flutter profile app  (1) 2025.01.08
'Flutter/App' 카테고리의 다른 글
  • [Flutter] 상태 관리 앱 만들기 (StatefulWidget 사용)
  • [Flutter] 상태 관리 앱 만들기 (stl, stf)
  • [Flutter] 연습하기 4 - Flutter Login app
  • [Flutter] Flutter Scroll Wiget
공돌이 출신 개발자
공돌이 출신 개발자
공돌이 출신 개발자입니다
  • 공돌이 출신 개발자
    공돌이 출신 개발자
    공돌이 출신 개발자
  • 전체
    오늘
    어제
    • 분류 전체보기 (124)
      • Database (0)
        • SQL (0)
        • 1일 1쿼리 (9)
      • Flutter (40)
        • Dart 언어 (18)
        • App (22)
      • Git (0)
      • Http 기초 지식 (14)
      • HTML5 & CSS3 (0)
      • Java (33)
      • JSP (0)
      • JavaScript (0)
      • Linux (0)
      • MSA (0)
      • Project (0)
      • React (0)
      • Spring (19)
      • 설치 메뉴얼 (1)
      • [Flutter] 프로젝트 (눈길) (8)
        • 작업일지 (8)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    dart
    로그인
    회원가입
    flutter
    앱개발
    SQLD
    SQL
    데이터
    공부
    개발
    메서드
    코딩
    프로그래밍
    1일1쿼리
    Java
    프로젝트
    Android
    안드로이드
    객체
    jsp
    spring boot
    객체지향
    HTTP
    안드로이드 앱 개발
    블로그 만들기
    android studio
    클래스
    앱 개발
    JAVA 기초
    플러터
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
공돌이 출신 개발자
[Flutter] 연습하기 4 - Flutter Shopping Cart app
상단으로

티스토리툴바