코드코도

[코독하구만 2] 5주차 - Flutter : Shop App 2 본문

Act/2021_여름_모각코_개인

[코독하구만 2] 5주차 - Flutter : Shop App 2

고도고도 고도고도 2021. 8. 10. 23:28
728x90

https://codekodo.tistory.com/88

 

[코독하구만 2] 4주차 - Flutter : Shop App

Udemy 강의가 어느덧 50퍼를 넘겼다. 중간에 어려운 부분도 몇 개 있었지만 이제 어느정도 혼자서 구축할 수 있을 것 같다. 사실 그때 그때 바로 정리하고 싶었는데 어쩌다보니 밀려서 오늘부터라

codekodo.tistory.com

지난 주에 일부 구현한 Shop App에 기능을 추가했다.

GridView로 표현한 아이템을 클릭하면 해당 아이템의 상세 정보를 보여준다.

import 'package:flutter/material.dart';
import '/providers/products.dart';
import 'package:provider/provider.dart';

class ProductDetailScreen extends StatelessWidget {
  static const routeName = '/product-detail';

  @override
  Widget build(BuildContext context) {
    final productId = ModalRoute.of(context).settings.arguments as String;
    final loadedProduct = Provider.of<Products>(
      context,
      listen: false,
    ).findById(productId); // 프로바이더가 제공한 데이터를 엑세스 가능
    return Scaffold(
        appBar: AppBar(
          title: Text(loadedProduct.title),
        ),
        body: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              Container(
                height: 300,
                width: double.infinity,
                child: Image.network(
                  loadedProduct.imageUrl,
                  fit: BoxFit.cover,
                ),
              ),
              SizedBox(
                height: 10,
              ),
              Text(
                '${loadedProduct.price}원',
                style: TextStyle(
                  color: Colors.grey,
                  fontSize: 20,
                ),
              ),
              SizedBox(
                height: 10,
              ),
              Container(
                padding : EdgeInsets.symmetric(horizontal: 10),
                width : double.infinity,
                child: Text(
                  loadedProduct.description,
                  textAlign: TextAlign.center,
                  softWrap: true,
                ),
              ),
            ],
          ),
        ));
  }
}

pushNamed로 넘겨받은 인자들을 Modalroute를 이용하여 가져온다.

이후 Product가 저장된 리스트에서 해당 상품을 찾고, 상품 사진, 상품명, 상품 가격을 보여준다.

 

다음은 상품 목록을 보여주고 관심 상품으로 체크하거나 장바구니에 담는 기능을 추가했다.

import 'package:flutter/material.dart';
import '/providers/products.dart';
import '/widgets/app_drawer.dart';
import '/screens/cart_screen.dart';
import '/providers/cart.dart';
import 'package:provider/provider.dart';
import '../widgets/products_grid.dart';
import '../widgets/badge.dart';

enum FilterOptions {
  Favorites,
  All,
}

class ProductsOverviewScreen extends StatefulWidget {
 @override
  _ProductsOverviewScreenState createState() => _ProductsOverviewScreenState();
}

class _ProductsOverviewScreenState extends State<ProductsOverviewScreen> {
  var _showOnlyFavorites = false;
  var _isInit = true;
  var _isLoading = false;

  @override
  void initState() {
    // Provider.of<Products>(context).fetchAndSetProducts(); -> context가 없는데 참고하므로 오류
    // Future.delayed(Duration.zero).then((_) {
    //   Provider.of<Products>(context).fetchAndSetProducts();
    // });
    super.initState();
  }

  @override
  void didChangeDependencies() {
    if (_isInit) {
      _isLoading = true;
      Provider.of<Products>(context).fetchAndSetProducts().then((_) {
        setState(() {
          _isLoading = false;
        });
      });
    }
    _isInit = false;
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('고도 쇼핑'),
        actions: <Widget>[
          PopupMenuButton(
            onSelected: (FilterOptions selectedValue) {
              setState(() {
                if (selectedValue == FilterOptions.Favorites) {
                  _showOnlyFavorites = true;
                } else {
                  _showOnlyFavorites = false;
                }
              });
            },
            icon: Icon(
              Icons.more_vert,
            ),
            itemBuilder: (_) => [
              PopupMenuItem(
                child: Text('관심상품만 보기'),
                value: FilterOptions.Favorites,
              ),
              PopupMenuItem(
                child: Text('모두 보기'),
                value: FilterOptions.All,
              ),
            ],
          ),
          Consumer<Cart>(
            builder: (_, cart, child) => // child는 build가 발생하지 않음
                Badge(
              child: child as Widget,
              value: cart.itemCount.toString(),
              color: Colors.red,
            ),
            child: IconButton(
              icon: Icon(
                Icons.shopping_cart,
              ),
              onPressed: () {
                Navigator.of(context).pushNamed(CartScreen.routeName);
              },
            ),
          ),
        ],
      ),
      drawer: AppDrawer(),
      body: _isLoading
          ? Center(
              child: CircularProgressIndicator(),
            )
          : ProductsGrid(_showOnlyFavorites),
    );
  }
}

 

PopupMenuButton을 이용하여 관심 상품 혹은 모든 상품을 볼 수 있도록 메뉴 선택지를 추가했다.

다음은 Consumer를 통해 Cart Provider에 접근하는데 Consumer의 child 속성을 통해 데이터의 변경이 일어나면

child로 선언한 부분만 갱신된다.

drawer는 따로 만들어준 AppDrawer 클래스를 넣어줬다.

이 부분은 좌측에 사이드바를 만들어주는 위젯 클래스이다.

 

AppDrawer 클래스를 살펴보자.

import 'package:flutter/material.dart';
import '/screens/user_product.dart';
import '/screens/orders_screen.dart';

class AppDrawer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: Column(
        children: <Widget>[
          AppBar(
            title: Text("안녕하세요, 고도현님"),
            automaticallyImplyLeading: false,
          ),
          Divider(),
          ListTile(
            leading: Icon(Icons.shop),
            title: Text('상품 확인'),
            onTap : () {
              Navigator.of(context).pushReplacementNamed('/');
            }
          ),
          Divider(),
          ListTile(
              leading: Icon(Icons.shopping_cart),
              title: Text('주문 내역'),
              onTap : () {
                Navigator.of(context).pushReplacementNamed(OrdersScreen.routeName);
              }
          ),
          Divider(),
          ListTile(
              leading: Icon(Icons.edit),
              title: Text('상품 관리'),
              onTap : () {
                Navigator.of(context).pushReplacementNamed(UserProductsScreen.routeName);
              }
          ),
        ],
      ),
    );
  }
}

ListTile로 사이드바로 표시할 요소들을 나타냈다.

이후 Divider로 ListTile 사이에 구분선이 들어가도록 구현했다.

 

소스코드는 아래 링크를 통해 접속하면 확인할 수 있다.

https://github.com/k906506/2021-Summer-Flutter-Study/tree/master/myfourthflutterapp

 

GitHub - k906506/2021-Summer-Flutter-Study: Studying hybrid app development using Dart and Flutter in summer vacation Mogakko

Studying hybrid app development using Dart and Flutter in summer vacation Mogakko 👾 - GitHub - k906506/2021-Summer-Flutter-Study: Studying hybrid app development using Dart and Flutter in summer va...

github.com

 

728x90
0 Comments
댓글쓰기 폼