반응형
이 사진처럼 만들려고 한다.
ListView를 이용해도 괜찮지만, 개수가 많지 않기 때문에 Column을 이요하려고 한다.
조금 더 쉽고 원하는 대로 수정할 수 있기 때문이다.
그리고, collection for을 이용한다.
FutureBuilder(
future: episodes,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: [
for (var episode in snapshot.data!)
Container(
이렇게, 당연하게도 FutureBuilder를 사용하고, data가 있는 경우에는 Column을 return하며, children을 collection for를 이용하여 Container를 episode의 개수에 맞춰서 출력한다.
나머지는 뭐... 그냥 열심히 꾸미면 된다.
detail_screen.dart 전체 코드를 첨부하겠다.
import 'package:flutter/material.dart';
import 'package:toonflix/models/webtoon_detail_model.dart';
import 'package:toonflix/services/api_service.dart';
import 'package:toonflix/models/webtoon_epsiode_model.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() {
super.initState();
webtoon = ApiService.getToonById(widget.id);
episodes = ApiService.getLatestEpisodesById(widget.id);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
elevation: 2,
surfaceTintColor: Colors.white,
shadowColor: Colors.black,
foregroundColor: Colors.green,
centerTitle: true,
title: Text(
widget.title,
style: const TextStyle(fontSize: 24),
),
),
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.5),
)
],
),
child: Image.network(widget.thumb),
),
),
],
),
const SizedBox(
height: 25,
),
FutureBuilder(
future: webtoon,
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!.gnere} / ${snapshot.data!.age}',
style: const TextStyle(
fontSize: 16,
),
),
],
);
}
return const Text("...");
},
),
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: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.green.shade400,
boxShadow: [
BoxShadow(
blurRadius: 1,
offset: const Offset(3, 4),
color: Colors.black.withOpacity(0.5),
),
],
),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 10,
horizontal: 20.0,
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
episode.title,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
),
),
const Icon(
Icons.chevron_right,
color: Colors.white,
),
],
),
),
),
],
);
}
return Container();
},
),
],
),
),
),
);
}
}
반응형
'앱 만들기 프로젝트 > Flutter' 카테고리의 다른 글
Flutter - 6.17 Favorites (1) | 2024.12.11 |
---|---|
Flutter - 6.16 Url Launcher (0) | 2024.12.10 |
Flutter - 6.14 Detail Info (0) | 2024.12.08 |
Flutter - 6.13 Futures (0) | 2024.12.08 |
Flutter - 6.12 ApiService (0) | 2024.12.08 |