Flutter/Flutter로 웹툰 앱 만들기

[노마드코더: Flutter 로 웹툰 앱 만들기] #6.15 Episodes

유호야 2022. 12. 20. 07:43
반응형
WebtoonEpisodeModel 
 

여기에서 아래 코드를 빼먹는 바람에 
return episodesInstances;

에러가 생겼었다. 지금은 찾아서 해결


detail_screen.dart에서

stateful위젯으로 변경한 이유는 

initState메서드가 필요하기 때문이다. 

그래야 getToonById와 getLatestEpisodesById가 필요하기 때문이다. 

 

ListView는 목록이 길 때 최적화에 좋게 사용하면 된다.
우리는 10개의 목록만 출력하기 때문에 Column을 이용할 것이다. 

만약에 길이를 몰랐다면 ListView를 사용하는 게 맞지만 우리는 10개의 길이를 알기 때문에 Column으로 고.

Collection for를 이용하고 있는데 
(for문을 보고 있음)
List 안에서 List를 빌드할 수 있도록 하는 기능이 있다. 

 

overflow문제가 발생할 때는 어떻게 한다? 

singChildScrollView로 감싸준다!

 


detail_sceen.dart

import 'package:flutter/material.dart';
import 'package:toonflix/models/webtoon_detail_model.dart';
import 'package:toonflix/models/webtoon_episode_model.dart';
import 'package:toonflix/services/api_service.dart';

class DetailScreen extends StatefulWidget {
  final String title, thumb, id;
  const DetailScreen({
    super.key,
    required this.title,
    required this.thumb,
    required this.id,
  });

  @override
  State<DetailScreen> createState() => _DetailScreenState();
}

class _DetailScreenState extends State<DetailScreen> {
  late Future<WebtoonDetailModel> webtoon;
  late Future<List<WebtoonEpisodeModel>> episodes;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    webtoon = ApiService.getToonById(widget.id);
    episodes = ApiService.getLatestEpisodesById(widget.id);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        elevation: 3,
        backgroundColor: Colors.white,
        foregroundColor: const Color.fromARGB(255, 13, 10, 0),
        title: Text(widget.title,
            style: const TextStyle(
              color: Colors.black,
            )),
      ),
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(50),
          child: Column(
            children: [
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Hero(
                    tag: widget.id,
                    child: Container(
                      width: 250,
                      clipBehavior: Clip.hardEdge,
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(15),
                        boxShadow: [
                          BoxShadow(
                            blurRadius: 15,
                            offset: const Offset(10, 10),
                            color: Colors.black.withOpacity(0.3),
                          )
                        ],
                      ),
                      child: Image.network(widget.thumb),
                    ),
                  ),
                ],
              ),
              const SizedBox(
                height: 25,
              ),
              FutureBuilder(
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(snapshot.data!.about,
                            style: const TextStyle(
                              fontSize: 16,
                            )),
                        const SizedBox(
                          height: 15,
                        ),
                        Text('${snapshot.data!.genre} / ${snapshot.data!.age}',
                            style: const TextStyle(
                              fontSize: 16,
                            )),
                      ],
                    );
                  }
                  return const Text('.....');
                },
                future: webtoon,
              ),
              const SizedBox(
                height: 25,
              ),
              FutureBuilder(
                future: episodes,
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return Column(
                      children: [
                        for (var episode in snapshot.data!)
                          Container(
                              margin: const EdgeInsets.only(
                                bottom: 5,
                              ),
                              decoration: BoxDecoration(
                                  color:
                                      const Color.fromARGB(255, 172, 191, 214)
                                          .withOpacity(0.6),
                                  borderRadius: BorderRadius.circular(25)),
                              child: Padding(
                                padding: const EdgeInsets.symmetric(
                                    vertical: 15, horizontal: 30),
                                child: Row(
                                  mainAxisAlignment:
                                      MainAxisAlignment.spaceBetween,
                                  children: [
                                    Text(episode.title),
                                    const Icon(Icons.chevron_right_rounded),
                                  ],
                                ),
                              )),
                      ],
                    );
                  }
                  return Container();
                },
              )
            ],
          ),
        ),
      ),
    );
  }
}

 

오늘은 코드 챌린지가 있다. 
버튼의 테두리만 색상 지정하기!

반응형