[Flutter] 스나이퍼팩토리 Flutter 도전하기 / 주간평가 (2주차)

GONG·2023년 4월 1일
0

도전하기

  • 카카오톡 친구 탭
// ignore_for_file: prefer_const_literals_to_create_immutables, prefer_const_constructors, file_names

import 'package:flutter/material.dart';
import 'package:badges/badges.dart' as badges;

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

class Friend {
  String img;
  String name;
  String? message;    // nullable
  String? music;    // nullable

  Friend({required this.img, required this.name, this.message, this.music});
}

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

  
  Widget build(BuildContext context) {
    List<Friend> friends = [
      Friend(img: 'http://picsum.photos/48/48', name: '전여친', message: '똥차다음벤츠라더니', music: '똥밟았네'),
      Friend(img: 'http://picsum.photos/48/48', name: '전여친'),
      Friend(img: 'http://picsum.photos/48/48', name: '전여친', message: '똥차다음벤츠라더니'),
      Friend(img: 'http://picsum.photos/48/48', name: '전여친', music: '똥밟았네'),
      Friend(img: 'http://picsum.photos/48/48', name: '전여친', message: '똥차다음벤츠라더니', music: '똥밟았네'),
      Friend(img: 'http://picsum.photos/48/48', name: '전여친', message: '똥차다음벤츠라더니', music: '똥밟았네'),
      Friend(img: 'http://picsum.photos/48/48', name: '전여친', message: '똥차다음벤츠라더니'),
      Friend(img: 'http://picsum.photos/48/48', name: '전여친', message: '똥차다음벤츠라더니', music: '똥밟았네'),
      Friend(img: 'http://picsum.photos/48/48', name: '전여친', message: '똥차다음벤츠라더니', music: '똥밟았네'),
      Friend(img: 'http://picsum.photos/48/48', name: '전여친', message: '똥차다음벤츠라더니', music: '똥밟았네'),
      Friend(img: 'http://picsum.photos/48/48', name: '전여친', message: '똥차다음벤츠라더니'),
      Friend(img: 'http://picsum.photos/48/48', name: '전여친', message: '똥차다음벤츠라더니', music: '똥밟았네'),
    ];

    return MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            backgroundColor: Colors.transparent,
            foregroundColor: Colors.black,
            elevation: 0,
            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.person_add_alt),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Icon(Icons.music_note_outlined),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Icon(Icons.settings_outlined),
              )
            ],
          ),
          body: ListView(
            children: [
              SizedBox(
                height: 80,
                child: PageView(
                  children: [
                    Image.asset('assets/images/kakaotalk/event_1.png'),
                    Image.asset('assets/images/kakaotalk/event_2.png'),
                  ],
                ),
              ),
              ListTile(
                leading: Container(
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(17),
                  ),
                  clipBehavior: Clip.antiAlias,
                  child: Image.network('http://picsum.photos/50/50'),
                ),
                title: Text('SFAC', style: TextStyle(fontWeight: FontWeight.bold),),
              ),
              Padding(
                padding: const EdgeInsets.fromLTRB(20, 10, 8, 20),
                child: Divider(
                  height: 2,
                ),
              ),
              Padding(
                padding: const EdgeInsets.only(left: 20),
                child: Text('친구 ${friends.length}'),
              ),
              Column(
                children: List.generate(
                  friends.length, (index) => ListTile(
                  leading: Container(
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(17),
                    ),
                    clipBehavior: Clip.antiAlias,
                    child: Image.network(friends[index].img),
                  ),
                  title: Text(friends[index].name, style: TextStyle(fontWeight: FontWeight.bold),),
                  subtitle: 
                  // message 존재하면 subtitle 보여주고 없으면 안보여주기
                  subtitle: friends[index].message != null ? Text(friends[index].message!) : null,
                  // music이 존재하면 trailing 보여주고 없으면 안보여주기
                  trailing: friends[index].music != null ?
                    Container(
                      width: 100,
                      decoration: BoxDecoration(
                          border: Border.all(color: Colors.green),
                          borderRadius: BorderRadius.circular(10)
                      ),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: [
                          Text(friends[index].music!),
                          Icon(Icons.play_arrow_outlined,color: Colors.green,),
                        ],
                      ),
                    ) : null,
                  ),
                )
              ),
            ],
          ),
          bottomNavigationBar: BottomNavigationBar(
            type: BottomNavigationBarType.fixed,
            selectedItemColor: Colors.black,
            showSelectedLabels: false,
            showUnselectedLabels: false,
            items: [
              BottomNavigationBarItem(
                icon: Icon(Icons.person), label: 'friends'),
              BottomNavigationBarItem(
                icon: badges.Badge(
                  badgeContent: Text('99', style: TextStyle(color: Colors.white),),
                  child: Icon(Icons.chat_bubble_outlined),), label: 'message'),
              BottomNavigationBarItem(
                  icon: Icon(Icons.remove_red_eye_outlined), label: 'view'),
              BottomNavigationBarItem(
                  icon: Icon(Icons.add_business), label: 'shop'),
              BottomNavigationBarItem(
                  icon: Icon(Icons.more_horiz), label: 'more'),
            ],
          ),
        )
    );
  }
}


주간평가 (키오스크 앱)

  • Output

Requirements

  1. 음식을 누르면 주문 리스트에 담기는 키오스크앱을 만들어봅니다.
  2. 음식이미지는 자유이며, 필요한 경우 위에 첨부된 파일을 이용하여도 됩니다.
  3. 하단에 떠있는 버튼을 누르면 지금까지 주문된 주문 리스트를 초기화합니다.
  4. 하단에 떠있는 버튼은 정중앙의 하단, 넓게 펴진 형태로 [ 초기화하기 ] 텍스트를 포함합니다.
  5. 음식이 보여지는 것은 [갤러리] 형태로 보여지게 하며, 검색을 통해 해결합니다.
  6. 그 외 UI 디자인은 자유입니다.
  • MenuTile.dart
    import 'package:flutter/material.dart';
    
    class MenuTile extends StatelessWidget {
      const MenuTile({Key? key, required this.imgUrl, required this.name}) : super(key: key);
    
      final String imgUrl;
      final String name;
    
      
      Widget build(BuildContext context) {
        return Container(
          decoration: BoxDecoration(
              boxShadow: const [
                BoxShadow(
                  color: Colors.black12,
                  blurRadius: 4,
                  spreadRadius: 1,
                )
              ]
          ),
          child: Container(
            color: Colors.white,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Container(
                  height: 75,
                  decoration: BoxDecoration(
                    image: DecorationImage(
                      image: AssetImage(imgUrl),
                      fit: BoxFit.cover,
                    )
                  ),
                ),
                Text(name, style: TextStyle(fontWeight: FontWeight.bold),),
                Text('[담기]'),
              ],
            ),
          ),
        );
      }
    }
    
  • Kiosk.dart
  • 메뉴를 담을 때 주문 리스트에 중복해서 출력하지 않고, 개수를 카운팅하여 주문 리스트에 메뉴 이름과 개수를 출력하는 형태로 구현했습니다
    import 'package:first_app/homework/week2/kiosk/MenuTile.dart';
    import 'package:flutter/material.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> {
      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 MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text('분식왕 이테디 주문하기', 
                style: TextStyle(color: Colors.black),),
              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),),
                    Text(countMenu.toString(),
                      style: TextStyle(fontSize: 16),),
                    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: FloatingActionButton.extended(
              onPressed: () {
                setState(() {
                  orderList.clear();
                  countMenu.clear();
                });
              },
              label: Text('초기화하기'),
            ),
          )
        );
      }
    }

profile
우와재밋다

0개의 댓글