기존 키오스크 앱 👉 [2주차] 주간평가
AdminPage.dart
import 'package:flutter/material.dart';
class AdminPage extends StatelessWidget {
const AdminPage({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Admin Page'),
),
body: Column(
children: [
ListTile(title: Text('메뉴 추가'),),
ListTile(title: Text('메뉴 삭제'),),
ListTile(title: Text('메뉴 수정'),),
],
),
);
}
}
MenuTile.dart 파일은 수정한 부분이 없습니다
Kiosk.dart
- 주간평가 과제 진행할 때 주문 리스트에 메뉴를 중복해서 새롭게 추가하지 않고 메뉴이름과 리스트에서 카운팅한 개수를 함께 보여주는 방식으로 구현해 둬서 이번 과제에서도 Chip 위젯의 삭제 버튼을 누르면 count 값을 1씩 줄이고, count 값이 0이 되면 위젯을 삭제하는 방식으로 구현했습니다
import 'package:first_app/homework/week2/kiosk/MenuTile.dart';
import 'package:flutter/material.dart';
import 'AdminPage.dart';
void main() {
runApp(const MyApp());
}
class Menu {
String imgUrl;
String name;
Menu(this.imgUrl, this.name);
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Widget build(BuildContext context) {
return MaterialApp(
home: Kiosk(),
);
}
}
class Kiosk extends StatefulWidget {
const Kiosk({Key? key}) : super(key: key);
State<Kiosk> createState() => _KioskState();
}
class _KioskState extends State<Kiosk> {
List<Menu> menuList = [
Menu('assets/images/kiosk/option_bokki.png', '떡볶이'),
Menu('assets/images/kiosk/option_beer.png', '맥주'),
Menu('assets/images/kiosk/option_kimbap.png', '김밥'),
Menu('assets/images/kiosk/option_omurice.png', '오므라이스'),
Menu('assets/images/kiosk/option_pork_cutlets.png', '돈까스'),
Menu('assets/images/kiosk/option_ramen.png', '라면'),
Menu('assets/images/kiosk/option_udon.png', '우동'),
];
// 주문할 메뉴들이 담긴 리스트
List<String> orderList = [];
// 주문할 메뉴와 각각의 개수를 키와 값 형태로 저장
Map<String, int> countMenu = {};
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: GestureDetector(
child: Text('분식왕 이테디 주문하기', style: TextStyle(color: Colors.black),),
onDoubleTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const AdminPage()),
);
},
),
centerTitle: true,
backgroundColor: Colors.white,
elevation: 0,
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('주문 리스트',
style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),),
SizedBox(
height: 40,
child: countMenu.isNotEmpty ? ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: countMenu.length,
itemBuilder: (context, index) {
String menu = countMenu.keys.elementAt(index);
int count = countMenu[menu] ?? 0;
return Chip(
label: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(menu),
Text('$count'),
],
),
onDeleted: () {
setState(() {
countMenu[menu] != null && countMenu[menu]! > 1 ?
countMenu[menu] = (countMenu[menu]! - 1) : countMenu.remove(menu);
});
},
);
},
) : Center(child: Text('주문한 메뉴가 없습니다'))
),
Text('음식',
style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),),
GridView.builder(
shrinkWrap: true,
itemCount: menuList.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
setState(() {
// 클릭한 메뉴 이름을 변수로 선언
String tapMenu = menuList[index].name;
// orderList에 클릭한 메뉴 이름 추가
orderList.add(tapMenu);
// countMenu 가 클릭한 메뉴를 키로 가지고 있다면
if(countMenu.containsKey(tapMenu)){
// 해당 키의 카운트 값 +1
countMenu[tapMenu] = countMenu[tapMenu]! + 1;
} else {
// 클릭한 메뉴를 키로 가지고 있지 않다면 카운트 값 1로 설정
countMenu[tapMenu] = 1;
}
});
},
child: MenuTile(
imgUrl: menuList[index].imgUrl,
name: menuList[index].name));
},
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: 1 / 1,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
),
],
),
)
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: countMenu.isNotEmpty ?
FloatingActionButton.extended(
onPressed: () {},
label: Text('결제하기'),
) : null
);
}
}
기존 연락처 앱 👉 [1주차] 주간평가
class Friend {
String img;
String name;
String phone;
Friend(this.img, this.name, this.phone);
}
class CallRecord {
String name;
CallType callType;
CallRecord(this.name, this.callType);
}
List<Friend> friendList = [
Friend('http://picsum.photos/50/50', '이테디', '010-1000-2000'),
Friend('http://picsum.photos/48/48', '김스틴', '010-9000-8000'),
Friend('http://picsum.photos/55/55', '이주노', '010-3000-3000'),
Friend('http://picsum.photos/60/60', '임헬렌', '010-2000-8000'),
Friend('http://picsum.photos/40/40', '염해리', '010-1000-1000'),
];
List<CallRecord> callRecordList = [
CallRecord('이테디', CallType.incoming),
CallRecord('김스틴', CallType.missed),
CallRecord('이주노', CallType.incoming),
CallRecord('임헬렌', CallType.missed),
CallRecord('임헬렌', CallType.outgoing),
CallRecord('염해리', CallType.incoming),
CallRecord('염해리', CallType.outgoing),
];
// 통화의 종류를 상수값의 집합으로 만들어서 사용
enum CallType {
incoming,
outgoing,
missed,
}
import 'package:flutter/material.dart';
class ContactTile extends StatelessWidget {
const ContactTile({super.key, required this.img, required this.name, required this.phone});
final String img;
final String name;
final String phone;
Widget build(BuildContext context) {
return ListTile(
leading: SizedBox(
width: 50, height: 50,
child: CircleAvatar(
backgroundImage: NetworkImage(img),
),
),
title: Text(name),
subtitle: Text(phone),
trailing: Icon(Icons.phone),
);
}
}
import 'package:flutter/material.dart';
import 'ContactScreen.dart';
import 'HistoryScreen.dart';
import 'SettingScreen.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
home: MainPage()
);
}
}
class MainPage extends StatefulWidget {
const MainPage({Key? key}) : super(key: key);
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
int tapIdx = 0;
List<Widget> pages = [
ContactScreen(),
HistoryScreen(),
SettingScreen()
];
onItemTap(index) {
setState(() {
tapIdx = index;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: false,
title: Text('내 연락처'),
actions: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(Icons.search),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(Icons.more_vert),
)
],
),
body: pages[tapIdx],
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: tapIdx,
onTap: onItemTap,
items: [
BottomNavigationBarItem(icon: Icon(Icons.quick_contacts_dialer), label: '연락처'),
BottomNavigationBarItem(icon: Icon(Icons.history), label: '통화기록'),
BottomNavigationBarItem(icon: Icon(Icons.settings), label: '설정'),
],
),
);
}
}
import 'package:flutter/material.dart';
import 'ContactDetailPage.dart';
import 'ContactData.dart';
import 'ContactTile.dart';
class ContactScreen extends StatefulWidget {
const ContactScreen({Key? key}) : super(key: key);
State<ContactScreen> createState() => _ContactScreenState();
}
class _ContactScreenState extends State<ContactScreen> {
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: friendList.length,
itemBuilder: (context, index) {
return GestureDetector(
child: ContactTile(
img: friendList[index].img,
name: friendList[index].name,
phone: friendList[index].phone,
),
onTap: () {
print(friendList[index].name);
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ContactDetailPage(friend: friendList[index])),
);
},
);
}
),
);
}
}
import 'package:flutter/material.dart';
import 'ContactData.dart';
import 'ContactTile.dart';
class ContactDetailPage extends StatelessWidget {
const ContactDetailPage({Key? key, required this.friend}) : super(key: key);
final Friend friend;
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
centerTitle: false,
backgroundColor: Colors.transparent,
elevation: 0,
title: Text('연락처 상세'),
actions: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(Icons.more_vert),
)
],
),
body: Column(
children: [
SizedBox(
width: double.infinity,
height: 200,
child: Image.network(friend.img, fit: BoxFit.fill,)
),
ContactTile(img: friend.img, name: friend.name, phone: friend.phone)
],
),
);
}
}
import 'package:flutter/material.dart';
import 'ContactData.dart';
class HistoryScreen extends StatelessWidget {
const HistoryScreen({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: callRecordList.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(callRecordList[index].name),
trailing: Icon(
(() {
switch (callRecordList[index].callType) {
case CallType.incoming:
return Icons.call_received;
case CallType.outgoing:
return Icons.call_made;
case CallType.missed:
return Icons.call_missed;
default:
return Icons.call;
}
}()), // 함수를 선언과 동시에 실행시키고 결과값 반환
),
);
}
),
);
}
}
import 'package:flutter/material.dart';
class SettingScreen extends StatelessWidget {
const SettingScreen({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
ListTile(title: Text('차단 목록')),
ListTile(title: Text('벨소리 설정')),
ListTile(title: Text('전화 통계')),
],
),
);
}
}