27일차 과제 - rlatkddbs99/Flutter GitHub Wiki
main.dart
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:user/page/mainPage.dart';
void main() async {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: mainPage(),
);
}
}
page/mainPage.dart
import 'package:animate_do/animate_do.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:user/model/profile.dart';
import 'package:user/page/detailPage.dart';
class mainPage extends StatefulWidget {
const mainPage({super.key});
@override
State<mainPage> createState() => _mainPageState();
}
class _mainPageState extends State<mainPage> {
List<Profile> profiles = []; //dio 결과 담을 리스트
readUsers() {
var url = "https://jsonplaceholder.typicode.com/users";
Dio dio = Dio();
dio.get(url).then((value) {
//결과가 얻어지면 value에는 future를 통해 얻어진 결과가 들어감
if (value.statusCode == 200) {
var data = List<Map<String, dynamic>>.from(
value.data); //List<dynamic>을 Map형식으로 바꿈
//print(value.data.runtimeType); List<dynamic>
profiles = data.map((e) => Profile.fromMap(e)).toList(); //하나하나 새로운값을 넣음
setState(() {}); //새로고침
}
});
}
@override
void initState() {
//생성될 때 한번 실행
super.initState();
readUsers();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("My Contacts"),
backgroundColor: Colors.transparent,
foregroundColor: Colors.black,
elevation: 0,
),
body: ListView.builder(
itemCount: profiles.length,
itemBuilder: (context, index) => FadeInRight(
delay: Duration(milliseconds: 100 * index), //스르륵 애니메이션
child: ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(
"https://xsgames.co/randomusers/assets/avatars/male/${profiles[index].id}.jpg"), //프로바이더 형태, userId를 이용함
),
title: Text(profiles[index].name),
subtitle: Text(profiles[index].email), //email내용
trailing: IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailPage(
profile: profiles[
index]))); //눌렀을 때 해당 페이지로 이동, 해당 유저 데이터 가지고감
},
icon: Icon(Icons.navigate_next)),
),
),
));
}
}
page/detailPage.dart
import 'package:animate_do/animate_do.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:user/model/profile.dart';
class DetailPage extends StatelessWidget {
const DetailPage({super.key, required this.profile});
final Profile profile;
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true, //사진이 앱바영역 까지 먹음
appBar: AppBar(
title: Text(profile.name), //현재 넘어온 사람의 name 앱바에 표시
elevation: 0,
backgroundColor: Colors.transparent,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Stack(
//위젯 겹치게 보이기
clipBehavior: Clip.none, //circleAvatar안잘리게
children: [
Image.network(
"https://xsgames.co/randomusers/assets/avatars/male/${profile.id}.jpg",
fit: BoxFit.cover,
colorBlendMode: BlendMode.darken, //이미지 살짝 어둡게
color: Colors.black45, //색깔 지정 필요
width: double.infinity, //이미지 가로 길이가 다 차지할 수 있도록
height: 320,
), //이미지 번호에 맞춰 가져오기
Positioned(
bottom: -48,
child: Padding(
padding: const EdgeInsets.only(left: 16), //왼쪽에 공백
child: CircleAvatar(
radius: 48,
backgroundImage: NetworkImage(
"https://xsgames.co/randomusers/assets/avatars/male/${profile.id}.jpg"),
),
),
)
],
),
SizedBox(
height: 56,
),
FadeInRight(
duration: Duration(milliseconds: 500),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
profile.name,
style: TextStyle(fontSize: 32),
),
Divider(
thickness: 2,
),
Text(
"Information",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
),
FadeInRight(
duration: Duration(milliseconds: 900),
child: Row(
children: [
Icon(Icons.email),
SizedBox(
width: 15,
),
Text(
profile.email,
style: TextStyle(fontSize: 13),
),
],
),
),
FadeInRight(
duration: Duration(milliseconds: 900),
child: Row(
children: [
Icon(Icons.phone),
SizedBox(
width: 15,
),
Text(
profile.phone,
style: TextStyle(fontSize: 13),
),
],
),
),
FadeInRight(
duration: Duration(milliseconds: 900),
child: Row(
children: [
Icon(Icons.pin_drop),
SizedBox(
width: 15,
),
Text(
//바로출력 못해 DataType이라 .으로 접근
profile.address.city +
profile.address.street +
profile.address.suite,
style: TextStyle(fontSize: 13),
),
],
),
),
SizedBox(height: 7),
FadeInRight(
duration: Duration(milliseconds: 1100),
child: Divider(
thickness: 2,
),
),
SizedBox(
height: 5,
),
Text("Company",
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 15)),
SizedBox(
height: 3,
),
FadeInRight(
duration: Duration(milliseconds: 1100),
child: Text(profile.company.name)),
FadeInRight(
duration: Duration(milliseconds: 1100),
child: Text(profile.company.catchPhrase)),
FadeInRight(
duration: Duration(milliseconds: 1100),
child: Text(profile.company.bs)),
],
),
),
)
],
),
);
}
}
model/profile.dart
import 'package:user/model/address.dart';
import 'package:user/model/company.dart';
class Profile {
int id;
String name;
String username;
String email;
Address address; //만들어뒀던거
String phone;
String website;
Company company; //만들어 둔거
Profile({
required this.id,
required this.name,
required this.username,
required this.email,
required this.address,
required this.phone,
required this.website,
required this.company,
});
factory Profile.fromMap(Map<String, dynamic> map) {
return Profile(
id: map['id'],
name: map['name'],
username: map['username'],
email: map['email'],
address: Address.fromMap(map['address']), //Address라는 클래스를 넘겨주기로 했으니까
phone: map['phone'],
website: map['website'],
company: Company.fromMap(map['company']),
);
}
}
model/address.dart
import 'package:user/model/geo.dart';
class Address {
String street;
String suite;
String city;
String zipcode;
Geo geo; //아까 만든 Geo클래스가 이 안에 속해있음
Address({
required this.street,
required this.suite,
required this.city,
required this.zipcode,
required this.geo,
});
factory Address.fromMap(Map<String, dynamic> map) {
return Address(
street: map["street"],
suite: map['suite'],
city: map['city'],
zipcode: map['zipcode'],
//geo: map['geo'] 안돼. 지금 Geo라는 클래스를 줘야 하는데 map이 넘어감
//map을 연결 시켜주면 돼
geo: Geo.fromMap(
map['geo']) //map의 형태인 map['geo']를 가지고 Geo라는 클래스를 만들고 일치하게 만듦
);
}
}
model/company.dart
class Company {
String name;
String catchPhrase;
String bs;
Company({
required this.name,
required this.catchPhrase,
required this.bs,
});
factory Company.fromMap(Map<String, dynamic> map) {
return Company(
name: map['name'], catchPhrase: map['catchPhrase'], bs: map['bs']);
}
}
model/geo.dart
class Geo {
String lat;
String lng;
Geo({
required this.lat,
required this.lng,
});
factory Geo.fromMap(Map<String, dynamic> map) {
return Geo(lat: map['lat'], lng: map['lng']);
}
}