25일차 과제 - rlatkddbs99/Flutter GitHub Wiki

강의 듣기 전 (구분선, bottomsheet 구현 전)

image

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'],
    );
  }
}

강의 후

Android Emulator - flutter_emulator_5554 2023-02-28 14-37-34

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'],
    );
  }
}
⚠️ **GitHub.com Fallback** ⚠️