ShoppingCartApp - 만들기

송민경's avatar
Apr 15, 2024
ShoppingCartApp - 만들기

1. 기본 셋팅하기

  • 파일 구조 잡기
notion image
  • 이미지 경로 설정하기
notion image
 

2. 각 클래스에서 작업하기

  • 커스텀 메터리얼 컬러 만들기
  • 기본 버튼 색깔, 활성화된 버튼 색깔 설정하기
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); //활성화 버튼
  • 만든 색깔을 이용한 테마 만들기
import 'package:flutter/material.dart'; import 'package:shopping_cart_app/constants.dart'; ThemeData theme() { return ThemeData( primarySwatch: kPrimaryColor, scaffoldBackgroundColor: kPrimaryColor, ); }
  • 헤더 만들기
  • 헤더는 각 페이지가 들어올 예정임
import 'package:flutter/cupertino.dart'; class ShoppingCartHeader extends StatefulWidget { const ShoppingCartHeader({super.key}); @override State<ShoppingCartHeader> createState() => _ShoppingCartHeaderState(); } class _ShoppingCartHeaderState extends State<ShoppingCartHeader> { int selectedId = 0; List<String> selectedPic = [ "assets/p1.jpeg", "assets/p2.jpeg", "assets/p3.jpeg", "assets/p4.jpeg", ]; @override Widget build(BuildContext context) { return SizedBox(); } }
  • 카트 상세보기
  • 추후 버튼이랑 텍스트 추가 예정
import 'package:flutter/cupertino.dart'; class ShoppingCartDetail extends StatelessWidget { const ShoppingCartDetail({super.key}); @override Widget build(BuildContext context) { return SizedBox(); } }
  • main에서 테마랑 홈 적용하기
  • 추후 상단 앱바 만들 예정
import 'package:flutter/material.dart'; import 'package:shopping_cart_app/components/shoppingcart_header.dart'; import 'package:shopping_cart_app/theme.dart'; import 'components/shoppingcart_detail.dart'; import 'constants.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, theme: theme(), home: ShoppingCartPage(), ); } } class ShoppingCartPage extends StatelessWidget { const ShoppingCartPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: _buildShoppingCartAppBar(), body: Column( children: [ ShoppingCartHeader(), ShoppingCartDetail(), ], ), ); } } AppBar _buildShoppingCartAppBar() { return AppBar(); }
notion image
 

3. 앱바 만들기

  • 테마 적용후에 앱바에 적용이 안되서 색상 적용하기
import 'package:flutter/material.dart'; import 'package:shopping_cart_app/components/shoppingcart_header.dart'; import 'package:shopping_cart_app/theme.dart'; import 'components/shoppingcart_detail.dart'; import 'constants.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, theme: theme(), home: ShoppingCartPage(), ); } } class ShoppingCartPage extends StatelessWidget { const ShoppingCartPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: _buildShoppingCartAppBar(), body: Column( children: [ ShoppingCartHeader(), ShoppingCartDetail(), ], ), ); } } AppBar _buildShoppingCartAppBar() { return AppBar( backgroundColor: kPrimaryColor, leading: IconButton( icon: Icon(Icons.arrow_back), onPressed: () {}, ), actions: [ IconButton( icon: Icon(Icons.shopping_cart), onPressed: () {}, ), SizedBox(width: 16), ], elevation: 0.0, ); }
notion image
 

4. 이미지 넣기

  • 비율로 이미지 크기 조절하기
import 'package:flutter/cupertino.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.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> { int selectedId = 0; List<String> selectedPic = [ "assets/p1.jpeg", "assets/p2.jpeg", "assets/p3.jpeg", "assets/p4.jpeg", ]; @override Widget build(BuildContext context) { return Column( children: [ _buildHeadPic(), ], ); } Widget _buildHeadPic() { return Padding( padding: const EdgeInsets.all(16), child: AspectRatio( aspectRatio: 5 / 3, child: Image.asset( selectedPic[selectedId], fit: BoxFit.cover, ), ), ); } }
notion image
 

5. 아이콘 버튼 만들기

import 'package:flutter/cupertino.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.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> { int selectedId = 0; List<String> selectedPic = [ "assets/p1.jpeg", "assets/p2.jpeg", "assets/p3.jpeg", "assets/p4.jpeg", ]; @override Widget build(BuildContext context) { return Column( children: [ _buildHeadPic(), _buildHeaderSelector(), ], ); } Widget _buildHeadPic() { return Padding( padding: const EdgeInsets.all(16), child: AspectRatio( aspectRatio: 5 / 3, child: Image.asset( selectedPic[selectedId], fit: BoxFit.cover, ), ), ); } Widget _buildHeaderSelector() { return Padding( padding: const EdgeInsets.only(left: 30, right: 30, top: 10, bottom: 30), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _buildHeaderSelectorButton(0, Icons.directions_bike), _buildHeaderSelectorButton(1, Icons.motorcycle), _buildHeaderSelectorButton(2, CupertinoIcons.car_detailed), _buildHeaderSelectorButton(2, CupertinoIcons.airplane), ], ), ); } Widget _buildHeaderSelectorButton(int id, IconData mIcon) { return Container( width: 70, height: 70, decoration: BoxDecoration( color: id == selectedId ? kAccentColor : kSecondaryColor, borderRadius: BorderRadius.circular(20), ), child: IconButton( icon: Icon(mIcon, color: Colors.black), onPressed: () { selectedId = id; }, ), ); } }
notion image
 

6. 텍스트 넣기

import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class ShoppingCartDetail extends StatelessWidget { const ShoppingCartDetail({super.key}); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(40), ), child: Padding( padding: const EdgeInsets.all(30), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildDetailNameAndPrice(), _buildDetailRatingAndReviewCount(), _buildDetailColorOptions(), _buildDetailButton(context), ], ), ), ); } Widget _buildDetailNameAndPrice() { return Padding( padding: const EdgeInsets.only(bottom: 10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Urban Soft AL 10.0", style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), ], ), ); } Widget _buildDetailRatingAndReviewCount() { return SizedBox(); } Widget _buildDetailColorOptions() { return SizedBox(); } Widget _buildDetailIcon(IconData mIcon) { return SizedBox(); } Widget _buildDetailButton(BuildContext context) { return SizedBox(); } }
notion image
 

7. 별점 및 후기 넣기

import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class ShoppingCartDetail extends StatelessWidget { const ShoppingCartDetail({super.key}); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(40), ), child: Padding( padding: const EdgeInsets.all(30), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildDetailNameAndPrice(), _buildDetailRatingAndReviewCount(), _buildDetailColorOptions(), _buildDetailButton(context), ], ), ), ); } Widget _buildDetailNameAndPrice() { return Padding( padding: const EdgeInsets.only(bottom: 10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Urban Soft AL 10.0", style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), ], ), ); } Widget _buildDetailRatingAndReviewCount() { return Padding( padding: EdgeInsets.only(bottom: 20), 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"), Text("(26)", style: TextStyle(color: Colors.blue)), ], ), ); } Widget _buildDetailColorOptions() { return SizedBox(); } Widget _buildDetailIcon(IconData mIcon) { return SizedBox(); } Widget _buildDetailButton(BuildContext context) { return SizedBox(); } }
notion image
 

8. 컬러 넣기

  • 색깔과 색깔보다 더 큰 박스 이용해서 테두리 만들기
  • 왼쪽, 위쪽 여백으로 위치 조절하기
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class ShoppingCartDetail extends StatelessWidget { const ShoppingCartDetail({super.key}); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(40), ), child: Padding( padding: const EdgeInsets.all(30), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildDetailNameAndPrice(), _buildDetailRatingAndReviewCount(), _buildDetailColorOptions(), _buildDetailButton(context), ], ), ), ); } Widget _buildDetailNameAndPrice() { return Padding( padding: const EdgeInsets.only(bottom: 10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Urban Soft AL 10.0", style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), ], ), ); } Widget _buildDetailRatingAndReviewCount() { return Padding( padding: EdgeInsets.only(bottom: 20), 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"), Text("(26)", style: TextStyle(color: Colors.blue)), ], ), ); } Widget _buildDetailColorOptions() { return Padding( padding: EdgeInsets.only(bottom: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Color Options"), SizedBox(height: 10), Row( children: [ _buildDetailIcon(Colors.black), _buildDetailIcon(Colors.green), _buildDetailIcon(Colors.orange), _buildDetailIcon(Colors.grey), _buildDetailIcon(Colors.white), ], ) ], ), ); } Widget _buildDetailIcon(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( left: 5, top: 5, child: ClipOval( child: Container( color: mColor, width: 40, height: 40, ), ), ) ], ), ); } Widget _buildDetailButton(BuildContext context) { return SizedBox(); } }
notion image
 

9. 텍스트 버튼 만들기

import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:shopping_cart_app/constants.dart'; class ShoppingCartDetail extends StatelessWidget { const ShoppingCartDetail({super.key}); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(40), ), child: Padding( padding: const EdgeInsets.all(30), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildDetailNameAndPrice(), _buildDetailRatingAndReviewCount(), _buildDetailColorOptions(), _buildDetailButton(context), ], ), ), ); } Widget _buildDetailNameAndPrice() { return Padding( padding: const EdgeInsets.only(bottom: 10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Urban Soft AL 10.0", style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), ], ), ); } Widget _buildDetailRatingAndReviewCount() { return Padding( padding: EdgeInsets.only(bottom: 20), 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"), Text("(26)", style: TextStyle(color: Colors.blue)), ], ), ); } Widget _buildDetailColorOptions() { return Padding( padding: EdgeInsets.only(bottom: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Color Options"), SizedBox(height: 10), Row( children: [ _buildDetailIcon(Colors.black), _buildDetailIcon(Colors.green), _buildDetailIcon(Colors.orange), _buildDetailIcon(Colors.grey), _buildDetailIcon(Colors.white), ], ) ], ), ); } Widget _buildDetailIcon(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( left: 5, top: 5, child: ClipOval( child: Container( color: mColor, width: 40, height: 40, ), ), ) ], ), ); } Widget _buildDetailButton(BuildContext context) { return Align( child: TextButton( onPressed: (){}, 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), ), ), ); } }
notion image
 

10. 텍스트 버튼에 창 띄우는 액션넣기

import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:shopping_cart_app/constants.dart'; class ShoppingCartDetail extends StatelessWidget { const ShoppingCartDetail({super.key}); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(40), ), child: Padding( padding: const EdgeInsets.all(30), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildDetailNameAndPrice(), _buildDetailRatingAndReviewCount(), _buildDetailColorOptions(), _buildDetailButton(context), ], ), ), ); } Widget _buildDetailNameAndPrice() { return Padding( padding: const EdgeInsets.only(bottom: 10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Urban Soft AL 10.0", style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), ], ), ); } Widget _buildDetailRatingAndReviewCount() { return Padding( padding: EdgeInsets.only(bottom: 20), 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"), Text("(26)", style: TextStyle(color: Colors.blue)), ], ), ); } Widget _buildDetailColorOptions() { return Padding( padding: EdgeInsets.only(bottom: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Color Options"), SizedBox(height: 10), Row( children: [ _buildDetailIcon(Colors.black), _buildDetailIcon(Colors.green), _buildDetailIcon(Colors.orange), _buildDetailIcon(Colors.grey), _buildDetailIcon(Colors.white), ], ) ], ), ); } Widget _buildDetailIcon(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( left: 5, top: 5, child: ClipOval( child: Container( color: mColor, width: 40, height: 40, ), ), ) ], ), ); } Widget _buildDetailButton(BuildContext context) { return Align( child: TextButton( onPressed: () { 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), ), ), ); } }
notion image
 

11. 창 버튼 액션넣기

import 'package:flutter/material.dart'; import 'package:shopping_cart_app/components/shoppingcart_header.dart'; import 'package:shopping_cart_app/theme.dart'; import 'components/shoppingcart_detail.dart'; import 'constants.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, theme: theme(), home: ShoppingCartPage(), ); } } class ShoppingCartPage extends StatelessWidget { const ShoppingCartPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: _buildShoppingCartAppBar(), body: Column( children: [ ShoppingCartHeader(), ShoppingCartDetail(), ], ), ); } } AppBar _buildShoppingCartAppBar() { return AppBar( backgroundColor: kPrimaryColor, leading: IconButton( icon: Icon(Icons.arrow_back), onPressed: () {}, ), actions: [ IconButton( icon: Icon(Icons.shopping_cart), onPressed: () {}, ), SizedBox(width: 16), ], elevation: 0.0, ); }
notion image
 
Share article

vosw1