<aside> ❓ 1. 다음화면을 구현해봅니다.
gif
다음의 URL에 데이터를 요청하여 문제를 해결합니다.
디바이스가 인터넷에 연결돼있는지 확인하는 패키지를 사용합니다.
화면을 아래로 당기면 데이터를 새로 요청할 수 있도록 패키지를 사용합니다.
데이터를 가져올 때 사용자에게 데이터가 로딩중이라는 것을 알려줄 수 있도록 패키지를 활용합니다.
위 기능을 우선적으로 구현하며, 최대한 자연스러운 UX를 구현할 수 있도록 합니다. 그 외 과제를 위한 기능 및 디자인은 자유입니다. </aside>
main.dart
import 'package:flutter/material.dart';
import 'home.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Home(),
);
}
}
home.dart
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'GridViewItem.dart';
import 'ShimmerGridView.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
var dio = Dio();
var url = '<https://sniperfactory.com/sfac/read_dogs>';
RefreshController refreshController = RefreshController(initialRefresh: false);
bool isLoading = false; // 로딩 중 상태
bool internetConnected = true; // 인터넷 연결 상태
// 새로고침
void onRefresh() async {
setState(() {});
refreshController.refreshCompleted();
}
// 인터넷 연결 상태 체크
Future checkInternetConnection() async {
setState(() {
isLoading = true; // 로딩 시작
});
await Future.delayed(Duration(seconds: 1));
var connectivityResult = await Connectivity().checkConnectivity();
if (connectivityResult == ConnectivityResult.none) { // 인터넷 연결 없음
setState(() {
internetConnected = false;
});
} else { // 인터넷 연결 있음
setState(() {
internetConnected = true;
});
}
setState(() { // 로딩 종료
isLoading = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('16일차 과제'),
),
body: isLoading // 로딩 중일 때
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('인터넷 연결 확인 중입니다'),
CircularProgressIndicator()
],
)
)
: internetConnected // 로딩중 아니면 인터넷 연결 여부 검사
? FutureBuilder( // 인터넷 연결 o
future: Future.delayed(Duration(seconds: 1), () => dio.get(url)),
builder: (context, snapshot) {
if(snapshot.connectionState == ConnectionState.waiting) {
return ShimmerGridView();
}
var data = snapshot.data?.data['body'];
if (snapshot.hasData && data != null) {
return SmartRefresher(
controller: refreshController,
enablePullDown: true,
onRefresh: onRefresh,
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
childAspectRatio: 3/4,
),
itemCount: data.length,
itemBuilder: (context, index) {
return GridItem(url: data[index]['url'], msg: data[index]['msg']);
}
),
);
} else {
return ShimmerGridView();
}
},
)
: Center( // 인터넷 연결 x
child: Text('인터넷 연결 없음'),
),
floatingActionButton: FloatingActionButton(
onPressed: checkInternetConnection,
child: Icon(Icons.wifi_find),
),
);
}
}
GridViewItem.dart
import 'package:flutter/material.dart';
class GridItem extends StatelessWidget {
const GridItem({Key? key, required this.url, required this.msg}) : super(key: key);
final String url;
final String msg;
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 180,
height: 180,
child: Image.network(url, fit: BoxFit.cover,),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: const [
BoxShadow(
color: Colors.black12,
blurRadius: 2,
spreadRadius: 1,
)
]
),
clipBehavior: Clip.antiAlias,
),
),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8, bottom: 8),
child: Text(msg),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Align(
alignment: Alignment.centerLeft,
child: Icon(Icons.comment),
),
),
],
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: const [
BoxShadow(
color: Colors.black12,
blurRadius: 2,
spreadRadius: 1,
)
]
),
);
}
}
ShimmerGridView.dart
import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';
class ShimmerGridView extends StatelessWidget {
const ShimmerGridView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
childAspectRatio: 3/4,
),
itemCount: 6,
itemBuilder: (context, index) => Shimmer.fromColors(
baseColor: Colors.grey[300]!,
highlightColor: Colors.grey[100]!,
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(15)
),
),
)
);
}
}