
1. 기본 셋팅하기
- 파일 구조 잡기

- 이미지 경로 설정하기

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();
}

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,
);
}

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,
),
),
);
}
}

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;
},
),
);
}
}

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();
}
}

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();
}
}

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();
}
}

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),
),
),
);
}
}

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),
),
),
);
}
}

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,
);
}

Share article