앱 만들기 프로젝트/Flutter

Flutter - 6.8 Webtoon Card

지나가는물리학부생 2024. 11. 28. 21:08
반응형

ListView.separated가 안에 있는 것이 지저분해서 밖으로 빼자.
Extract Method의 code action을 이용했고, 이름은 makeList로 하였다:

  ListView makeList(AsyncSnapshot<List<WebtoonModel>> snapshot) {
    return ListView.separated(
      scrollDirection: Axis.horizontal,
      itemCount: snapshot.data!.length,
      itemBuilder: (context, index) {
        var webtoon = snapshot.data![index];
        return Text(webtoon.title);
      },
      separatorBuilder: (context, index) => const SizedBox(width: 20),
    );
  }
}

그리고...

          if (snapshot.hasData) {
            return Column(
              children: [
                const SizedBox(
                  height: 50,
                ),
                makeList(snapshot)
              ],
            );
          }

이렇게 Column으로 위에 공간을 좀 내고 그 아래에 정보를 출력하도록 만들어 보자.

그러면, error가 난다.
이것은 ListView에는 '높이'가 존재하지 않기 때문이다.
그러니까, 무한한 높이이다. 그래서 ListView만 써도 자동으로 스크롤이 가능했나보다.
그래서 높이를 직접 줘야 한다. Expanded를 이용한다.

Expanded는 화면의 남는 공간을 차지하는 widget이다.

          if (snapshot.hasData) {
            return Column(
              children: [
                const SizedBox(
                  height: 50,
                ),
                Expanded(child: makeList(snapshot)),
              ],
            );
          }

이렇게 하면 된다.

이번에는 makeList를 살펴보자. 이미지를 불러올 것이다.

  ListView makeList(AsyncSnapshot<List<WebtoonModel>> snapshot) {
    return ListView.separated(
      scrollDirection: Axis.horizontal,
      itemCount: snapshot.data!.length,
      itemBuilder: (context, index) {
        var webtoon = snapshot.data![index];
        return Column(
          children: [
            Image.network(webtoon.thumb),
            Text(webtoon.title),
          ],
        );
      },
      separatorBuilder: (context, index) => const SizedBox(width: 40),
    );
  }

Image.network(webtoon.thumb), 이 부분이다.
(만약 에러가 난다면, 이 링크를 참조해 보자: https://gist.github.com/preinpost/941efd33dff90d9f8c7a208da40c18a9)

나는 두 번째 방법인:

import 'dart:io';

class MyHttpOverrides extends HttpOverrides {
  @override
  HttpClient createHttpClient(SecurityContext? context) {
    return super.createHttpClient(context)
      ..userAgent =
          'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36';
  }
}

이 방법을 사용했는데, 그래도 제대로 로드가 안되어서 continue를 몇 번 누르다 보면 이미지가 불러와진다.

그리고 이제 썸네일 부분을 열심히 꾸몄다.

  ListView makeList(AsyncSnapshot<List<WebtoonModel>> snapshot) {
    return ListView.separated(
      scrollDirection: Axis.horizontal,
      itemCount: snapshot.data!.length,
      // padding 안주면 그림자 위쪽이 짤림
      padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
      // ListView의 아이템을 만드는 역할
      itemBuilder: (context, index) {
        // 0, 1, 2같은 index로만 접근 가능.
        var webtoon = snapshot.data![index];
        return Column(
          children: [
            Container(
              width: 250,
              // clipbehavior를 적용해야 둥근 모서리가 적용이 된다.
              clipBehavior: Clip.hardEdge,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(15),
                // 그림자 관련 옵션
                boxShadow: [
                  BoxShadow(
                    // blurRadius : 그림자 크기
                    blurRadius: 15,
                    // offset : 그림자 위치
                    offset: const Offset(10, 10),
                    // color : 그림자 색
                    color: Colors.black.withOpacity(0.5),
                  )
                ],
              ),
              child: Image.network(webtoon.thumb),
            ),
            const SizedBox(
              height: 10,
            ),
            Text(
              webtoon.title,
              style: const TextStyle(
                fontSize: 22,
              ),
            ),
          ],
        );
      },
      separatorBuilder: (context, index) => const SizedBox(width: 40),
    );
  }

꾸미는건 직접 만져보면서 해봐야 아는거라... 넘어가도록 하자.

반응형