GridView 위젯
- 리스트 뷰와 마찬가지로 항목을 나열하는 위젯이지만, 리스트 뷰와 달리 한 줄에 여러 개를 함께 나열할 수 있음
(그리드 형태) - 리스트 뷰와 마찬가지로 그리드뷰도 GridView.builder() 생성자를 제공하며,
- itemCount, itemBuilder 속성을 통해 항목의 개수와 위젯을 지정
- gridDelegate 속성을 설정해야 함
- 이 속성에는 SliverGridDelegateWithFixedCrossAxisCount 객체를 지정해줘야 함
- 해당 객체에서 crossAxisCount 값이 한 줄에 함께 나와야 하는 항목의 개수임
- 그리드 두 방향을 설정하지 않으면, crossAxisCount는 가로를 가리킴
- 참고: scrollDirection 속성에 Axis.horizontal을 설정하면, crossAxisCount는 세로 방향을 가리킴
프로젝트 생성
프로젝트 이름 : class_v03
main.dart
더보기
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
// build 메서드가 Painting 한다.
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('그리드뷰 위젯 연습'),
),
body: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 16,
mainAxisSpacing: 16
),
itemCount: 10,
itemBuilder: (context, index) {
return Container(
color: Colors.blueGrey,
child: Center(child: Text('index number : + $index')),
);
},
),
),
);
}
}

PageView 위젯
- 스와이프 이벤트에 반응하여 항목을 보여주는 위젯
- PageController의 initialPage로 처음 보일 페이지를 설정할 수 있고, viewportFraction으로 현재 페이지가 화면에 차지하는 비율도 설정 가능
- 예: viewportFraction: 0.7이면 현재 페이지가 화면에 70%, 나머지 30%가 이전과 다음 페이지가 살짝 보이게 됨
- PageController 객체를 PageView의 controller 속성에 적용하여, PageController 설정을 반영시킬 수 있음
main1.dart
더보기
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp1());
}
class MyApp1 extends StatelessWidget {
const MyApp1({super.key});
@override
// build 메서드가 Painting 한다.
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('페이지 뷰 위젯 연습'),
),
body: PageView(
controller: PageController(
initialPage: 2,
viewportFraction: 0.9
),
children: [
Container(
margin: EdgeInsets.all(10),
color: Colors.redAccent,
),
Container(
margin: EdgeInsets.all(10),
color: Colors.blueGrey,
),
Container(
margin: EdgeInsets.all(10),
color: Colors.green,
)
],
),
),
);
}
}



쇼핑 카트 앱 만들어

https://github.com/flutter-coder/flutter-book/tree/master/flutter_shoppingcart
flutter-book/flutter_shoppingcart at master · flutter-coder/flutter-book
Contribute to flutter-coder/flutter-book development by creating an account on GitHub.
github.com

작업 순서
pubspec.yaml 이미지 폴더 위치 설정
constants.dart 파일 작업
theme.dart 파일 작업
.. header.dart
… details.dart
assets 폴더 만들기

사진 업로드




pubspec.yaml
더보기
# To add assets to your application, add an assets section, like this:
assets:
- assets//
# - images/a_dot_ham.jpeg
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:flutter_shoppingcart/constants.dart';
ThemeData theme() {
return ThemeData(
primarySwatch: kPrimaryColor,
scaffoldBackgroundColor: kPrimaryColor,
);
}
shoppingcart_header.dart
더보기
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_shoppingcart/constants.dart';
class ShoppingCartHeader extends StatefulWidget {
const ShoppingCartHeader({Key? key}) : super(key: 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: [
_buildHeaderPic(),
_buildHeaderSelector(),
],
);
}
Widget _buildHeaderPic() {
return Padding(
padding: const EdgeInsets.all(16.0),
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(3, CupertinoIcons.airplane),
],
),
);
}
// 1. 다른 화면에서도 재사용하면 공통 컴포넌트 위젯으로 관리하는 것이 좋다.
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: () {
setState(() {
selectedId = id;
});
},
),
);
}
}
main.dart
더보기
import 'package:flutter/material.dart';
import 'package:flutter_shoppingcart/components/shoppingcart_detail.dart';
import 'package:flutter_shoppingcart/components/shoppingcart_header.dart';
import 'package:flutter_shoppingcart/theme.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: theme(),
home: ShoppingCartPage(),
);
}
}
class ShoppingCartPage extends StatelessWidget {
const ShoppingCartPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _buildShoppingCartAppBar(),
body: Column(
children: [
ShoppingCartHeader(),
Expanded(child: ShoppingcartDetail())
],
),
);
}
AppBar _buildShoppingCartAppBar() {
return AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {},
),
actions: [
IconButton(
icon: Icon(Icons.shopping_cart),
onPressed: () {},
),
SizedBox(width: 16),
],
elevation: 0.0,
);
}
}
shoppingcart_detail.dart
더보기
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_shoppingcart/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.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildDetailNameAndPrice(),
_buildDetailRatingAndReviewCount(),
_buildDetailColorOptions(),
_buildDetailButton(context),
],
),
),
);
}
Widget _buildDetailNameAndPrice() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Urban Soft AL 10.0',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
Text(
'\$699',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
],
);
}
Widget _buildDetailRatingAndReviewCount() {
return Padding(
padding: const EdgeInsets.only(bottom: 20.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),
// row 위젯 기준으로 남은 여백 다 차지
Spacer(),
Text('Review '),
Text(
'(26)',
style: TextStyle(color: Colors.blue),
),
],
),
);
}
Widget _buildDetailColorOptions() {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
Text('Color Options'),
SizedBox(height: 10),
Row(
children: [
// 재 사용을 위해 함수로 설계
_buildDetailIcons(Colors.black),
_buildDetailIcons(Colors.green),
_buildDetailIcons(Colors.orange),
_buildDetailIcons(Colors.white),
],
)
],
),
);
}
// 여러번 추후 호출 해야 한다.
Widget _buildDetailIcons(Color mColor) {
return Padding(
padding: const 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: () {
// alert dialog 사용법
// 플랫폼 별 준비,
// 1. showDialog 호출
// 2.ios -> showCupertinoDialog
showCupertinoDialog(context: context, builder: (context) {
return CupertinoAlertDialog(
actions: [
CupertinoDialogAction(child: Text('확인'),onPressed: () {
// 플러터 프레임워크가
// 화면간이 이동시에 위젯들이
// 스택구조로 관리해주는 객체이다.
Navigator.pop(context);
}),
],
);
},);
},
style: TextButton.styleFrom(
backgroundColor: kAccentColor,
maximumSize: Size(300, 50),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
),
child: Text(
'Add to Cart',
style: TextStyle(
color: Colors.white,
),
),
),
);
}
}
'Flutter' 카테고리의 다른 글
| 2024. 11. 12 Dio 통신 연습 (0) | 2024.11.12 |
|---|---|
| 2024. 11. 12 플러터 기본기 다지기 - 3 (0) | 2024.11.12 |
| 2024. 11. 08 플러터 기본기 다지기 - 3 (0) | 2024.11.08 |
| 2024.11.07 플러터 기본기 다지기 - 2 (폰트 설정, 로컬 이미지) (2) | 2024.11.07 |
| 2024.11.07 flutter 플러터 기본기 다지기 - 1 (0) | 2024.11.07 |