4주차 주간평가 - rlatkddbs99/Flutter GitHub Wiki

Android Emulator - flutter_emulator_5554 2023-02-19 20-31-55

main.dart

import 'package:flutter/material.dart';
import 'package:test1/pages/HomePage.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(), //home페이지 호출
    );
  }
}

HomePage.dart

import 'package:animated_bottom_navigation_bar/animated_bottom_navigation_bar.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:secret_cat_sdk/api/api.dart';
import 'package:test1/pages/authorPage.dart';
import 'package:test1/pages/secretPage.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  var _bottomIndex = 0; //인덱스로 페이지 이동
  List pages = [
    secretPage(),
    authorPage(),
  ]; //이동할 페이지 리스트
  @override
  Widget build(BuildContext context) {
    var controller = TextEditingController(); //컨트롤러 설정
    return Scaffold(
      drawer: Drawer(
        child: ListView(
          children: [
            DrawerHeader(child: Text("비밀듣는 고양이 (SNS형)\n스나이퍼 팩토리 교육용앱")),
            ListTile(
              title: Text("Teddy"),
              leading: FaIcon(FontAwesomeIcons.dev),
            )
          ],
        ),
      ),
      appBar: AppBar(
        elevation: 0,
        backgroundColor: Colors.transparent,
        foregroundColor: Colors.black,
        title: Text(
          "비밀듣는 고양이",
          style: TextStyle(color: Colors.black),
        ),
      ),
      floatingActionButton: FloatingActionButton(
          backgroundColor: Colors.orange,
          onPressed: () {
            showModalBottomSheet<void>(
                isScrollControlled: true, //텍스트 필드 위로 올리기 위함
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(16),
                ),
                context: context,
                builder: (BuildContext context) {
                  return Container(
                    padding: EdgeInsets.only(
                        bottom: MediaQuery.of(context)
                            .viewInsets
                            .bottom), //텍스트 필드 위로 올리기 위함
                    child: Column(
                      mainAxisSize: MainAxisSize.min, //전체 다 컨테이너가 먹는거 방지
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: [
                        Text(
                          "비밀을 공유해볼까요?",
                          textAlign: TextAlign.center,
                        ),
                        SizedBox(
                          height: 4,
                        ),
                        TextField(
                          controller: controller,
                          minLines: 3,
                          maxLines: 7,
                          decoration: InputDecoration(
                              hintText: "비밀을 입력하세요.",
                              filled: true,
                              fillColor: Colors.white24),
                        ),
                        SizedBox(
                          height: 8,
                        ),
                        ElevatedButton(
                            style: ElevatedButton.styleFrom(
                                primary: Colors.orangeAccent),
                            onPressed: () async {
                              if (controller.text != "") {
                                //텍스트필드 비었을 때 방지
                                var secret = await SecretCatApi.addSecret(
                                    //텍스트 필드에 있는 텍스트를 비밀에 추가
                                    controller.text);
                                if (secret != null) {
                                  //비밀을 작성했으면 내려줌
                                  Navigator.pop(context);
                                }
                              }
                            },
                            child: Text("공유하기"))
                      ],
                    ),
                  );
                });
          },
          child: Icon(
            Icons.add,
            color: Colors.white,
          )),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      body: pages[_bottomIndex], //페이지 확인, 맞는 페이지 설정
      bottomNavigationBar: AnimatedBottomNavigationBar(
        icons: [
          FontAwesomeIcons.cat,
          FontAwesomeIcons.peopleGroup,
        ],
        activeIndex: _bottomIndex, //이동할 페이지
        gapLocation: GapLocation.center,
        onTap: (index) {
          setState(() {
            _bottomIndex = index;
          });
        },
      ),
    );
  }
}

secretPage.dart

import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:secret_cat_sdk/api/api.dart';
import 'package:intl/intl.dart';
import 'package:test1/SecretCard.dart';

class secretPage extends StatefulWidget {
  const secretPage({super.key});

  @override
  State<secretPage> createState() => _secretPageState();
}

class _secretPageState extends State<secretPage> {
  RefreshController _refreshController = RefreshController();   //새로고침

  void _onRefresh() async {     //새로고침할 때 할거
    setState(() {
      var result = SecretCatApi.fetchSecrets();
    });
    _refreshController.loadComplete();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: SecretCatApi.fetchSecrets(),    //뭐할건지, 비밀가져올거야
      builder: ((context, snapshot) {
        if (snapshot.hasData) {   //snapshot에 데이터 있는지
          return SmartRefresher(
            controller: _refreshController,   //컨트롤러 연결
            onRefresh: _onRefresh,  //함수 연결
            enablePullDown: true,   //내렸을 때 새로고침
            header: WaterDropHeader(),    //새로고침 할 때 모습
            child: ListView.builder(  //어떤 걸 새로고침할지
                itemCount: snapshot.data?.length,   //표시할 데이터 개수, null이면 계속 생성
                itemBuilder: ((context, index) => 
                    SecretCard(secret: snapshot.data![index]))),  //SecretCard호출 하는데 데이터가져가기 거기 필수 속성 secret에 어떤 데이터 들어가는지
          );
        }
        return CircularProgressIndicator();     //로딩
      }),
    );
  }
}

SecretCard.dart

import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:intl/intl.dart';
import 'package:secret_cat_sdk/model/secret.dart';

class SecretCard extends StatelessWidget {
  const SecretCard({super.key, required this.secret});
  final Secret secret;
  @override
  Widget build(BuildContext context) {
    return Container(
      //카드 표현
      margin: EdgeInsets.all(8),
      padding: EdgeInsets.all(8),
      decoration: BoxDecoration(
          color: Colors.white12,
          borderRadius: BorderRadius.circular(16),
          border: Border.all(width: 0.5, color: Colors.grey)),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          ListTile(
            title: Text(
              secret.author?.username ??
                  "익명", //다른 거랑 다르게 secret으로 데이터 접근, secretPage에서 secret으로 데이터 알려줌
            ),
            subtitle: Text(DateFormat("E, MM/dd")
                .format(secret.createdAt)), //날짜포멧형식 날자, 몇월/몇일
            leading: CircleAvatar(
                radius: 24,
                backgroundImage: secret.author != null //데이터 접근하기
                    ? NetworkImage(secret.author!.avatar
                        .toString()) //이미지 글자로 접근, 맞는 아바타 이미지 없으면 null로 표현
                    : null),
          ),
          Divider(
            height: 3,
          ),
          Padding(
            padding: const EdgeInsets.all(24),
            child: Text(secret.secret),
          )
        ],
      ),
    );
  }
}

authorPage.dart

import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:secret_cat_sdk/api/api.dart';

class authorPage extends StatefulWidget {
  const authorPage({super.key});

  @override
  State<authorPage> createState() => _authorPageState();
}

class _authorPageState extends State<authorPage> {
  RefreshController _refreshController = RefreshController();

  void _onRefresh() async {
    setState(() {
      var res = SecretCatApi.fetchAuthors();
    });
    _refreshController.refreshCompleted();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: SecretCatApi.fetchAuthors(), //작성자 가져오기
      builder: ((context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          //hasData랑 똑같음
          return SmartRefresher(
            controller: _refreshController,
            enablePullDown: true,
            onRefresh: _onRefresh,
            header: WaterDropHeader(),
            child: ListView.builder(
              itemCount: snapshot.data?.length,
              itemBuilder: ((context, index) {
                return ListTile(
                  title: Text(snapshot.data![index].username), //데이터 접근
                  leading: CircleAvatar(
                    radius: 24,
                    backgroundImage:
                        NetworkImage(snapshot.data![index].avatar!),
                  ),
                );
              }),
            ),
          );
        }
        return CircularProgressIndicator();
      }),
    );
  }
}
⚠️ **GitHub.com Fallback** ⚠️