name27 / flutter

0 stars 0 forks source link

도전과제: 강아지 앱 #80

Open name27 opened 1 year ago

name27 commented 1 year ago

image image image image

main.dart

import 'package:final_dog_app/pages/main_page.dart';
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';

void main() async {
  await Hive.initFlutter();
  await Hive.openBox('myBox');
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MainPage(),
    );
  }
}

main_page.dart

import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dio/dio.dart';
import 'package:final_dog_app/DogCard.dart';
import 'package:final_dog_app/LikeList.dart';
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:final_dog_app/pages/loading_page.dart';
import 'package:final_dog_app/pages/checkWifi_page.dart';

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

  @override
  State<MainPage> createState() => _MainPageState();
}

var box = Hive.box('myBox');

class _MainPageState extends State<MainPage> {
  var dio = Dio();
  var url = "https://sfacassignment-default-rtdb.firebaseio.com/.json";
  List<Map<String, dynamic>> dogList = [];
  String wifiText = "";
  bool isWaitWifi = true;

  var _gridViewController = ScrollController();
  var _refreshController = RefreshController();

  void initState() {
    super.initState();
    checkWifi();
  }

  void _onRefresh() async {
    setState(() {});
    await Future.delayed(Duration(milliseconds: 2000));
    _refreshController.refreshCompleted();
  }

  checkWifi() async {
    dogList = [];
    wifiText = "인터넷 연결 확인 중입니다.";
    await Future.delayed(const Duration(milliseconds: 1500));
    final connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.mobile) {
      print("모바일 네트워크 연결 확인");
      isWaitWifi = false;
    } else if (connectivityResult == ConnectivityResult.wifi) {
      print("와이파이 연결 확인");
      isWaitWifi = false;
    } else {
      wifiText = "인터넷 연결이 되지 않습니다";
    }
  }

  getData() async {
    var res = await dio.get(url);
    for (int i = 0; i < res.data["body"].length; i++) {
      dogList.add({});
      dogList[i].addAll({
        "msg": "${res.data["body"][i]["msg"]}",
        "url": "${res.data["body"][i]["url"]}"
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: GestureDetector(
            onTap: () {
              _gridViewController.animateTo(0,
                  duration: Duration(milliseconds: 300), curve: Curves.easeIn);
            },
            child: Text('도전하기')),
        centerTitle: true,
        actions: [
          LikeList(
            box: box,
          )
        ],
      ),
      body: Center(
          child: FutureBuilder(
        future: checkWifi(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done && !isWaitWifi) {
            return FutureBuilder(
              future: getData(),
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.done) {
                  return _dogCard();
                } else {
                  return LoadingPage();
                }
              },
            );
          } else if (!isWaitWifi) {
            return LoadingPage();
          } else {
            return CheckWifiPage(
              wifiText: wifiText,
            );
          }
        },
      )),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          isWaitWifi = true;
          checkWifi();
          setState(() {});
        },
        child: Icon(Icons.wifi_find),
      ),
    );
  }

  Widget _dogCard() {
    return SmartRefresher(
        enablePullUp: false,
        header: WaterDropHeader(
            waterDropColor: Colors.transparent,
            idleIcon: Icon(
              Icons.refresh_outlined,
              size: 35,
            )),
        controller: _refreshController,
        onRefresh: _onRefresh,
        child: GridView.builder(
          controller: _gridViewController,
          gridDelegate:
              SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
          itemCount: dogList.length,
          itemBuilder: (context, index) => DogCard(
            dogList: dogList[index],
            box: box,
          ),
        ));
  }
}

checkWifi_page.dart

import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter/widgets.dart';

class CheckWifiPage extends StatelessWidget {
  const CheckWifiPage({super.key, required this.wifiText});
  final String wifiText;

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(wifiText),
        CircularProgressIndicator(),
        SizedBox(
          width: 200.0,
          height: 100.0,
        )
      ],
    );
  }
}

loading_page.dart

import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';

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

  @override
  Widget build(BuildContext context) {
    return Shimmer.fromColors(
        baseColor: Colors.grey.shade300,
        highlightColor: Colors.grey.shade100,
        child: GridView.builder(
          gridDelegate:
              SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
          itemCount: 8,
          itemBuilder: (context, index) => Card(
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(15),
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Container(
                  height: 120,
                ),
                SizedBox(height: 3),
                Center(child: Text('')),
                SizedBox(height: 3),
                IconButton(onPressed: () {}, icon: Icon(Icons.chat))
              ],
            ),
          ),
        ));
  }
}

dog_page.dart

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

class Dogpage extends StatelessWidget {
  const Dogpage(
      {super.key,
      required this.imgUrl,
      required this.msg,
      required this.dogList});
  final String imgUrl;
  final String msg;
  final dynamic dogList;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Hero(
              tag: dogList,
              child: Container(
                width: 300,
                height: 300,
                decoration: BoxDecoration(
                    image: DecorationImage(
                        image: NetworkImage(imgUrl), fit: BoxFit.contain)),
              ),
            ),
            Text(
              msg,
              style: TextStyle(fontSize: 18),
            )
          ],
        ),
      ),
    );
  }
}

DogCard.dart

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:hive_flutter/hive_flutter.dart';

import 'pages/dog_page.dart';

class DogCard extends StatefulWidget {
  const DogCard({
    super.key,
    required this.dogList,
    required this.box,
  });
  final dynamic dogList;
  final Box<dynamic> box;

  @override
  State<DogCard> createState() => _DogCardState();
}

class _DogCardState extends State<DogCard> {
  @override
  Widget build(BuildContext context) {
    return Card(
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(15),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Hero(
              tag: widget.dogList,
              child: Material(
                child: Container(
                  height: 120,
                  decoration: BoxDecoration(
                      image: DecorationImage(
                          image: NetworkImage(widget.dogList["url"]),
                          fit: BoxFit.contain)),
                ),
              ),
            ),
            SizedBox(height: 3),
            Center(child: Text(widget.dogList["msg"])),
            SizedBox(height: 3),
            Row(
              children: [
                IconButton(
                    onPressed: () {
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => Dogpage(
                                    imgUrl: widget.dogList["url"],
                                    msg: widget.dogList["msg"],
                                    dogList: widget.dogList,
                                  )));
                    },
                    icon: Icon(Icons.chat)),
                IconButton(
                  onPressed: () {
                    if (widget.box.get(widget.dogList["msg"]) == null) {
                      widget.box.put(widget.dogList["msg"],
                          [widget.dogList["url"], widget.dogList["msg"]]);
                    } else {
                      widget.box.delete(widget.dogList["msg"]);
                    }
                    setState(() {});
                  },
                  icon: ValueListenableBuilder(
                    valueListenable: widget.box.listenable(),
                    builder: (BuildContext context, box, child) {
                      return FaIcon(FontAwesomeIcons.solidHeart,
                          color: box.get(widget.dogList["msg"]) != null
                              ? Colors.red
                              : Colors.grey);
                    },
                  ),
                ),
              ],
            )
          ],
        ));
  }
}

LikeList.dart

import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

class LikeList extends StatefulWidget {
  const LikeList({super.key, this.box});
  final dynamic box;

  @override
  State<LikeList> createState() => _LikeListState();
}

class _LikeListState extends State<LikeList> {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        IconButton(
          onPressed: () {
            showModalBottomSheet<void>(
              context: context,
              builder: (BuildContext context) {
                return ListView.builder(
                  itemCount: widget.box.values.toList().length,
                  itemBuilder: (context, index) => Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Row(
                      children: [
                        Container(
                          width: 65,
                          height: 65,
                          decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(12),
                              image: DecorationImage(
                                  image: NetworkImage(widget.box.values
                                      .toList()[index][0]
                                      .toString()),
                                  fit: BoxFit.cover)),
                        ),
                        SizedBox(
                          width: 8,
                        ),
                        Text(
                          widget.box.values.toList()[index][1].toString(),
                          style: TextStyle(
                              fontWeight: FontWeight.w600, wordSpacing: -1),
                        )
                      ],
                    ),
                  ),
                );
              },
            );
          },
          icon: FaIcon(
            FontAwesomeIcons.solidHeart,
            color: Colors.red,
          ),
        ),
        IconButton(
          onPressed: () {
            setState(() {
              widget.box.clear();
            });
          },
          icon: Icon(Icons.close),
        ),
      ],
    );
  }
}

사용패키지

dependencies:
  flutter:
    sdk: flutter
  connectivity_plus: ^3.0.3
  pull_to_refresh: ^2.0.0
  shimmer: ^2.0.0
  dio: ^5.0.0
  font_awesome_flutter: ^10.4.0
  flutter_native_splash: ^2.2.17
  hive: ^2.2.3
  hive_flutter: ^1.1.0
  hero_animation: ^1.0.0+1
name27 commented 1 year ago

Hive