25일차 과제 - rlatkddbs99/Flutter GitHub Wiki
main.dart
import 'package:blog/page/mainPage.dart';
import 'package:flutter/material.dart';
void main() async {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: mainPage(),
);
}
}
mainPage.dart
import 'package:blog/model/post.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 '../widget/postDetail.dart';
class mainPage extends StatefulWidget {
const mainPage({super.key});
@override
State<mainPage> createState() => _mainPageState();
}
class _mainPageState extends State<mainPage> {
Future<List<Post>> readData() async {
//post 여러개 가져오기
Dio dio = Dio();
var url = "https://jsonplaceholder.typicode.com/posts";
var response = await dio.get(url);
if (response.statusCode == 200) {
var data = List<Map<String, dynamic>>.from(
response.data); //바꿀 형태 써주고 from매개변수는 받아온 데이터 넣어
return data
.map((e) => Post.fromMap(e))
.toList(); //안에 있는 데이터Map형들이 하나하나 실행되면서 Post.fromMap의 형태로 바뀜
//map함수는 iterable형태를 보내기때문에 toList로 바꿈
}
return [];
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: readData(),
builder: ((context, snapshot) {
if (snapshot.hasData) {
return ListView.separated(
itemBuilder: ((context, index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
postDetail(post: snapshot.data![index]),
],
);
}),
separatorBuilder: ((context, index) {
Divider(
thickness: 3,
);
return SizedBox();
}),
itemCount: snapshot.data!.length);
}
return Center(
child: CircularProgressIndicator(),
);
}),
));
}
}
postDetail.dart
import 'package:blog/model/post.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
class postDetail extends StatelessWidget {
const postDetail({super.key, required this.post});
final Post post;
@override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: CircleAvatar(
child: Text(post.id.toString()),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
post.title,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
Text(post.body)
],
),
),
)
],
);
}
}
post.dart
class Post {
int userId;
int id;
String title;
String body;
Post(
{required this.userId,
required this.id,
required this.title,
required this.body});
factory Post.fromMap(Map<String, dynamic> map) {
return Post(
userId: map['userId'],
id: map['id'],
title: map['title'],
body: map['body'],
);
}
}
main.dart
import 'package:blog/page/mainPage.dart';
import 'package:flutter/material.dart';
void main() async {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.from(colorScheme: ColorScheme.dark()),
home: mainPage(),
);
}
}
mainPage.dart
import 'package:blog/model/post.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 '../widget/postDetail.dart';
class mainPage extends StatefulWidget {
const mainPage({super.key});
@override
State<mainPage> createState() => _mainPageState();
}
class _mainPageState extends State<mainPage> {
Future<List<Post>> readData() async {
//post 여러개 가져오기
Dio dio = Dio();
var url = "https://jsonplaceholder.typicode.com/posts";
var response = await dio.get(url);
if (response.statusCode == 200) {
var data = List<Map<String, dynamic>>.from(
response.data); //바꿀 형태 써주고 from매개변수는 받아온 데이터 넣어
return data
.map((e) => Post.fromMap(e))
.toList(); //안에 있는 데이터Map형들이 하나하나 실행되면서 Post.fromMap의 형태로 바뀜
//map함수는 iterable형태를 보내기때문에 toList로 바꿈
}
return [];
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: readData(),
builder: ((context, snapshot) {
if (snapshot.hasData && snapshot.data != null) {
//data있는지 null이 아닌지
return ListView.separated(
itemBuilder: ((context, index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
postDetail(
post: snapshot.data![
index]), //customwidget만들기 데이터 넘겨줄건데 인덱스에 해당하는 post데이터 보내기
],
);
}),
itemCount: snapshot.data!.length, //리스트뷰 길이지정 데이터 있는만큼
separatorBuilder: (context, index) => ((index + 1) % 5 == 0)
? Text(
"Post ${index + 2} ~ ${index + 5 + 1}",
style: TextStyle(fontSize: 16),
)
: SizedBox()
//index가 0부터 시작하니까 1늘려주고 나머지 연산. 삼항연산자로 출력하는데 인덱스 번호 맞춰주기
);
}
return Center(
child: CircularProgressIndicator(),
);
}),
));
}
}
postDetail.dart
import 'package:blog/model/post.dart';
import 'package:blog/widget/post_bottom_sheet.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
class postDetail extends StatelessWidget {
const postDetail({super.key, required this.post});
final Post post; //post보낸거 받기
@override
Widget build(BuildContext context) {
return ListTile(
onTap: () {
//이벤트 처리 따로 안해주고 여기서 해도돼
showModalBottomSheet(
context: context,
builder: (context) => PostBottmSheet(
post: post), //빌더에 컨텍스트 넣고 위젯 넣고싶은거 처리, 또 Post넘겨줄거야
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)));
},
title: Text(post.title),
subtitle: Text(post.body),
leading: CircleAvatar(
child: Text(post.id.toString()),
),
);
}
}
post_bottom_Sheet.dart
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import '../model/post.dart';
class PostBottmSheet extends StatelessWidget {
const PostBottmSheet({super.key, required this.post});
final Post post; //post기본으로 넘겨주기로 했으니까
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(8),
height: 250,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
post.title,
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(post.body)
],
));
}
}
post.dart
class Post {
int userId;
int id;
String title;
String body;
Post(
{required this.userId,
required this.id,
required this.title,
required this.body});
factory Post.fromMap(Map<String, dynamic> map) {
return Post(
userId: map['userId'],
id: map['id'],
title: map['title'],
body: map['body'],
);
}
}