
1. 기본 셋팅하기
- 파일 구조 잡기
 
      재사용 가능한 models, 각 화면들(컴포넌트, 페이지), 테마

- 구글과 폰트어썸 이모티콘 사용을 위한 셋팅하기
 
  cupertino_icons: ^1.0.2
  google_fonts: ^6.1.0
  font_awesome_flutter: ^10.5.0
  intl: ^0.18.1
2. 홈 화면 뼈대 만들기
import 'package:flutter/cupertino.dart';
class MainScreens extends StatefulWidget {
  @override
  State<MainScreens> createState() => _MainScreensState();
}
class _MainScreensState extends State<MainScreens> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: const Text("MainScreens"),
      ),
    );
  }
}
import 'package:flutter/material.dart';
import 'screens/main_screens.dart';
import 'theme.dart';
void main() {
  runApp(const CarrotMarket());
}
class CarrotMarket extends StatelessWidget {
  const CarrotMarket({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'carrot_market',
      home: MainScreens(),
      theme: theme(),
    );
  }
}- 기본 실행앱이 myApp에서 변경되어서 오류가 남
 
- 이름을 바꿔주면 사용 가능하나 테스트를 할 건 아니라 그냥 삭제하기
 

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class MainScreens extends StatefulWidget {
  @override
  State<MainScreens> createState() => _MainScreensState();
}
class _MainScreensState extends State<MainScreens> {
  int _seletedIndex = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: IndexedStack(
        index: _seletedIndex,
        children: [
          Container(
            color: Colors.orange[100],
            child: Center(
              child: Text(
                "IndexedStack 1",
                style: TextStyle(fontSize: 20, color: Colors.black),
              ),
            ),
          ),
          Container(
            color: Colors.orange[100],
            child: Center(
              child: Text(
                "IndexedStack 2",
                style: TextStyle(fontSize: 20, color: Colors.black),
              ),
            ),
          ),
        ],
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: [
          BottomNavigationBarItem(
            label: "홈",
            icon: Icon(
              CupertinoIcons.chat_bubble,
            ),
          ),
        ],
        onTap: (index){
          setState(() {
            _seletedIndex = index;
          },);
        },
        currentIndex: _seletedIndex,
      ),
    );
  }
}import 'package:flutter/cupertino.dart';
class ChattingScreen extends StatelessWidget {
  const ChattingScreen({super.key});
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text("chattingScreen"),
    );
  }
}import 'package:flutter/cupertino.dart';
class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text("homeScreen"),
    );
  }
}import 'package:flutter/cupertino.dart';
class MyCarrotScreen extends StatelessWidget {
  const MyCarrotScreen({super.key});
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text("myCattorScreen"),
    );
  }
}import 'package:flutter/cupertino.dart';
class NearMeScreen extends StatelessWidget {
  const NearMeScreen({super.key});
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text("nearMeScreen"),
    );
  }
}
import 'package:flutter/cupertino.dart';
class NeighborhoodLifeScreen extends StatelessWidget {
  const NeighborhoodLifeScreen({super.key});
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text("neighborhoodLifeScreen"),
    );
  }
}import 'package:carrot_market_ui/screens/chatting/chatting_sceen.dart';
import 'package:carrot_market_ui/screens/home/home_screen.dart';
import 'package:carrot_market_ui/screens/my_carrot/my_carrot_screen.dart';
import 'package:carrot_market_ui/screens/near_me/near_me_screen.dart';
import 'package:carrot_market_ui/screens/neighborhood_life/neighborhood_life_screen.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class MainHolder extends StatefulWidget {
  @override
  _MainScreensState createState() => _MainScreensState();
}
class _MainScreensState extends State<MainHolder> {
  int _selectedIndex = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: IndexedStack(
        index: _selectedIndex,
        children: [HomeScreen(), NeighborhoodLifeScreen(), NearMeScreen(), ChattingScreen(), MyCarrotScreen()],
      ),
      bottomNavigationBar: BottomNavigationBar(
        backgroundColor: Colors.white,
        type: BottomNavigationBarType.fixed,
        currentIndex: _selectedIndex,
        onTap: (index) {
          setState(() {
            _selectedIndex = index;
          });
        },
        items: [
          const BottomNavigationBarItem(label: '홈', icon: Icon(CupertinoIcons.home)),
          const BottomNavigationBarItem(label: '동네생활', icon: Icon(CupertinoIcons.square_on_square)),
          const BottomNavigationBarItem(label: '내 주변', icon: Icon(CupertinoIcons.placemark)),
          const BottomNavigationBarItem(label: '채팅', icon: Icon(CupertinoIcons.chat_bubble_2)),
          const BottomNavigationBarItem(label: '나의 당근', icon: Icon(CupertinoIcons.person)),
        ],
      ),
    );
  }
}
import 'package:carrot_market_ui/theme.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("HomeScreen appbar 영역(index:0)"),
      ),
      body: Container(
        color: Colors.orange[100],
        child: Center(
          child: Text(
            "HomeScreen body 영역(index:0)",
            style: textTheme().displayMedium,
          ),
        ),
      ),
    );
  }
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Row(
          children: [
            const Text("좌동"),
            const SizedBox(width: 4.0),
            const Icon(CupertinoIcons.chevron_down, size: 15.0),
          ],
        ),
        actions: [
          IconButton(
              icon: const Icon(CupertinoIcons.list_dash), onPressed: () {}),
          IconButton(icon: const Icon(CupertinoIcons.bell), onPressed: () {}),
        ],
        bottom: const PreferredSize(
          preferredSize: Size.fromHeight(0.5),
          child: Divider(thickness: 0.5, height: 0.5, color: Colors.grey),
        ),
      ),
      body: Container(),
    );
  }
}
class Product {
  String title;
  String author;
  String address;
  String urlToImage;
  String publishedAt;
  String price;
  int heartCount;
  int commentsCount;
  Product({
    required this.title,
    required this.author,
    required this.address,
    required this.urlToImage,
    required this.publishedAt,
    required this.price,
    required this.heartCount,
    required this.commentsCount,
  });
}
// 샘플 데이터
List<Product> productList = [
  Product(
      title: '니트 조끼',
      author: 'author_1',
      urlToImage: 'https://github.com/flutter-coder/ui_images/blob/master/carrot_product_7.jpg?raw=true',
      publishedAt: '2시간 전',
      heartCount: 8,
      price: '35000',
      address: '좌동',
      commentsCount: 3),
  Product(
      title: '먼나라 이웃나라 12',
      author: 'author_2',
      urlToImage: 'https://github.com/flutter-coder/ui_images/blob/master/carrot_product_6.jpg?raw=true',
      publishedAt: '3시간 전',
      heartCount: 3,
      address: '중동',
      price: '18000',
      commentsCount: 1),
  Product(
    title: '캐나다구스 패딩조',
    author: 'author_3',
    address: '우동',
    urlToImage: 'https://github.com/flutter-coder/ui_images/blob/master/carrot_product_5.jpg?raw=true',
    publishedAt: '1일 전',
    heartCount: 0,
    price: '15000',
    commentsCount: 12,
  ),
  Product(
    title: '유럽 여행',
    author: 'author_4',
    address: '우동',
    urlToImage: 'https://github.com/flutter-coder/ui_images/blob/master/carrot_product_4.jpg?raw=true',
    publishedAt: '3일 전',
    heartCount: 4,
    price: '15000',
    commentsCount: 11,
  ),
  Product(
    title: '가죽 파우치 ',
    author: 'author_5',
    address: '우동',
    urlToImage: 'https://github.com/flutter-coder/ui_images/blob/master/carrot_product_3.jpg?raw=true',
    publishedAt: '1주일 전',
    heartCount: 7,
    price: '95000',
    commentsCount: 4,
  ),
  Product(
    title: '노트북',
    author: 'author_6',
    address: '좌동',
    urlToImage: 'https://github.com/flutter-coder/ui_images/blob/master/carrot_product_2.jpg?raw=true',
    publishedAt: '5일 전',
    heartCount: 4,
    price: '115000',
    commentsCount: 0,
  ),
  Product(
    title: '미개봉 아이패드',
    author: 'author_7',
    address: '좌동',
    urlToImage: 'https://github.com/flutter-coder/ui_images/blob/master/carrot_product_1.jpg?raw=true',
    publishedAt: '5일 전',
    heartCount: 8,
    price: '85000',
    commentsCount: 3,
  ),
];import 'package:flutter/cupertino.dart';
import '../../models/product.dart';
import 'product_detail.dart';
class ProductItem extends StatelessWidget {
  final Product product;
  ProductItem({required this.product});
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 135.0,
      padding: const EdgeInsets.all(16.0),
      child: Row(
        children: [
          ClipRRect(
            borderRadius: BorderRadius.circular(10.0),
            child: Image.network(
              product.urlToImage,
              width: 115,
              height: 115,
              fit: BoxFit.cover,
            ),
          ),
          const SizedBox(width: 16.0),
          ProductDetail(product: product)
        ],
      ),
    );
  }
}import 'package:flutter/cupertino.dart';
import 'package:intl/intl.dart'; // Import the intl package for NumberFormat
import '../../models/product.dart';
import '../../theme.dart';
class ProductDetail extends StatelessWidget {
  final Product product;
  const ProductDetail({required this.product});
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(product.title, style: textTheme().bodyLarge),
          const SizedBox(height: 4.0),
          Text('${product.address} • ${product.publishedAt}'),
          const SizedBox(height: 4.0),
          Text(
            '${numberFormat(product.price)}원',
            style: textTheme().displayMedium,
          ),
          const Spacer(),
          Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
              Visibility(
                visible: product.commentsCount > 0,
                child: _buildIcons(
                  product.commentsCount,
                  CupertinoIcons.chat_bubble_2,
                ),
              ),
              const SizedBox(width: 8.0),
              Visibility(
                visible: product.heartCount > 0,
                child: _buildIcons(
                  product.heartCount,
                  CupertinoIcons.heart,
                ),
              ),
            ],
          )
        ],
      ),
    );
  }
  String numberFormat(String price) {
    final formatter = NumberFormat('#,###');
    return formatter.format(int.parse(price));
  }
  Widget _buildIcons(int count, IconData iconData) {
    return Row(
      children: [
        Icon(iconData, size: 14.0),
        const SizedBox(width: 4.0),
        Text('$count'),
      ],
    );
  }
}
import 'package:carrot_market_ui/models/product.dart';
import 'package:carrot_market_ui/screens/components/product_item.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Row(
          children: [
            const Text('좌동'),
            const SizedBox(width: 4.0),
            const Icon(
              CupertinoIcons.chevron_down,
              size: 15.0,
            ),
          ],
        ),
        actions: [
          IconButton(icon: const Icon(CupertinoIcons.search), onPressed: () {}),
          IconButton(
              icon: const Icon(CupertinoIcons.list_dash), onPressed: () {}),
          IconButton(icon: const Icon(CupertinoIcons.bell), onPressed: () {})
        ],
        bottom: const PreferredSize(
          preferredSize: Size.fromHeight(0.5),
          child: Divider(thickness: 0.5, height: 0.5, color: Colors.grey),
        ),
      ),
      body: ListView.separated(
        separatorBuilder: (context, index) => const Divider(
          height: 0,
          indent: 16,
          endIndent: 16,
          color: Colors.grey,
        ),
        itemBuilder: (context, index) {
          return ProductItem(
            product: productList[index],
          );
        },
        itemCount: productList.length,
      ),
    );
  }
}
Share article