ListView.builder, separated

샤워실의 바보·2023년 11월 13일
0
post-thumbnail
import 'package:flutter/material.dart';
import 'package:toonflix/models/webtoon_model.dart';
import 'package:toonflix/services/api_service.dart';

class HomeScreen extends StatelessWidget {
  HomeScreen({super.key});

  final Future<List<WebtoonModel>> webtoons = ApiService.getTodaysToons();

  
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        elevation: 2,
        backgroundColor: Colors.white,
        foregroundColor: Colors.green,
        title: const Text(
          "어늘의 웹툰",
          style: TextStyle(
            fontSize: 24,
          ),
        ),
      ),
      body: FutureBuilder(
        future: webtoons,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return Column(
              children: [
                const SizedBox(
                  height: 50,
                ),
                Expanded(child: makeList(snapshot))
              ],
            );
          }
          return const Center(
            child: CircularProgressIndicator(),
          );
        },
      ),
    );
  }

  ListView makeList(AsyncSnapshot<List<WebtoonModel>> snapshot) {
    return ListView.separated(
      scrollDirection: Axis.horizontal,
      itemCount: snapshot.data!.length,
      padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
      itemBuilder: (context, index) {
        var webtoon = snapshot.data![index];
        return Column(
          children: [
            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(webtoon.thumb),
            ),
            const SizedBox(
              height: 10,
            ),
            Text(
              webtoon.title,
              style: const TextStyle(
                fontSize: 22,
              ),
            ),
          ],
        );
      },
      separatorBuilder: (context, index) => const SizedBox(width: 40),
    );
  }
}

Flutter 코드에서 ListView.builder는 웹툰 이미지와 제목의 스크롤 가능한 목록을 만드는 데 사용됩니다. ListView.builder의 작동 방식과 코드에서의 사용 방법을 자세히 살펴보겠습니다:

ListView.builder 설명

ListView.builder는 Flutter에서 위젯의 선형 배열을 스크롤 가능하게 만드는 ListView 위젯의 생성자입니다. 많은 수의 아이템이 있는 목록에 특히 유용하며, 필요할 때마다 아이템을 생성하기 때문에 모든 아이템을 한 번에 생성하는 것보다 효율적입니다. 이 지연 로딩 방식은 메모리 사용량과 로딩 시간을 줄여 성능을 개선합니다.

ListView.builder의 주요 속성은 다음과 같습니다:

  • itemCount: 목록에 있는 아이템의 수를 지정합니다. 여기서는 Future에서 반환된 데이터의 길이입니다.
  • itemBuilder: 목록의 각 아이템에 대해 호출되는 함수입니다. 이 함수는 해당 아이템에 표시되는 위젯을 반환합니다. 함수는 BuildContext와 아이템 인덱스를 받습니다.

ListView.builder의 장점

애플리케이션에서 ListView.builder를 사용하면 여러 가지 이점이 있습니다:

  1. 효율성: 화면에 표시되는 아이템만 렌더링하여, 큰 목록에 대해 메모리 효율적입니다.
  2. 확장성: 성능 저하 없이 많은 수의 아이템을 처리할 수 있습니다.
  3. 유연성: 목록의 각 아이템의 모양과 레이아웃을 사용자 정의할 수 있습니다.

전반적으로, ListView.builder는 특히 큰 데이터셋을 다룰 때 부드러운 성능과 사용자 정의 가능성을 보장하면서 동적 목록을 생성하는 데 이상적인 선택입니다.

맞습니다, separatorBuilderListView.separated 생성자에서 사용되는 속성입니다. ListView.builderListView.separated는 비슷하지만, ListView.separated는 추가적으로 각 아이템 사이에 구분자를 만들기 위한 separatorBuilder를 제공합니다. 코드에서 사용된 ListView.separated의 사용 방법을 다시 설명하겠습니다.

ListView.separated

ListView.separated 생성자는 ListView.builder와 유사한 기능을 제공하지만, 각 아이템 사이에 구분자를 추가할 수 있는 기능이 포함되어 있습니다. 이는 아이템 사이에 공간을 두거나, 구분선을 추가하는 등의 목적으로 사용됩니다.

주요 속성은 다음과 같습니다:

  • itemCount: 목록에 있는 아이템의 수입니다.
  • itemBuilder: 각 아이템에 대해 호출되는 함수로, 해당 아이템을 위한 위젯을 반환합니다.
  • separatorBuilder: 아이템 사이의 구분자를 만드는 데 사용됩니다. 각 구분자에 대해 호출되며, 구분자를 위한 위젯을 반환합니다.

ListView.separated 사용 예시

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

여기서 ListView.separated는 다음과 같이 사용됩니다:

  • itemBuilder: 웹툰의 이미지와 제목을 표시하는 위젯을 만듭니다.
  • separatorBuilder: 각 웹툰 아이템 사이에 고정된 너비(40)의 SizedBox를 삽입하여 간격을 만듭니다.

ListView.separated는 아이템과 아이템 사이의 시각적 분리가 필요할 때 유용합니다. 이 방법은 리스트의 아이템이 서로 구분되도록 하여 전체적인 UI의 가독성을 향상시킵니다.

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:tiktok_clone/constants/gaps.dart';
import 'package:tiktok_clone/constants/sizes.dart';

class VideoComments extends StatefulWidget {
  const VideoComments({super.key});

  
  State<VideoComments> createState() => _VideoCommentsState();
}

class _VideoCommentsState extends State<VideoComments> {
  void _onClosePressed() {
    Navigator.of(context).pop();
  }

  
  Widget build(BuildContext context) {
    return Container(
      clipBehavior: Clip.hardEdge,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(Sizes.size14),
      ),
      child: Scaffold(
        backgroundColor: Colors.grey.shade50,
        appBar: AppBar(
          backgroundColor: Colors.grey.shade50,
          automaticallyImplyLeading: false,
          title: const Text("22796 comments"),
          actions: [
            IconButton(
              onPressed: _onClosePressed,
              icon: const FaIcon(FontAwesomeIcons.xmark),
            ),
          ],
        ),
        body: ListView.separated(
          padding: const EdgeInsets.symmetric(
            vertical: Sizes.size10,
            horizontal: Sizes.size16,
          ),
          separatorBuilder: (context, index) => Gaps.v20,
          itemCount: 10,
          itemBuilder: (context, index) => Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const CircleAvatar(
                radius: 18,
                child: Text("니꼬"),
              ),
              Gaps.h10,
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      '니꼬',
                      style: TextStyle(
                          fontWeight: FontWeight.bold,
                          fontSize: Sizes.size14,
                          color: Colors.grey.shade500),
                    ),
                    Gaps.v3,
                    const Text(
                        "That's not it l've seen the same thing but also in a cave,")
                  ],
                ),
              ),
              Gaps.h10,
              Column(
                children: [
                  FaIcon(
                    FontAwesomeIcons.heart,
                    size: Sizes.size20,
                    color: Colors.grey.shade500,
                  ),
                  Gaps.v2,
                  Text(
                    '52.2K',
                    style: TextStyle(
                      color: Colors.grey.shade500,
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
        bottomNavigationBar: BottomAppBar(
          color: Colors.white,
          child: Row(
            children: [
              CircleAvatar(
                radius: 18,
                backgroundColor: Colors.grey.shade500,
                foregroundColor: Colors.white,
                child: const Text("니꼬"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
ListView.separated(
  padding: const EdgeInsets.symmetric(
    vertical: Sizes.size10,
    horizontal: Sizes.size16,
  ),
  separatorBuilder: (context, index) => Gaps.v20,
  itemCount: 10,
  itemBuilder: (context, index) => Row(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      // ... (코드 생략)
    ],
  ),
)
  1. padding:

    • ListView의 내부 여백을 정의합니다.
    • EdgeInsets.symmetric을 사용하여 세로(vertical) 여백은 Sizes.size10으로, 가로(horizontal) 여백은 Sizes.size16으로 설정되었습니다.
  2. separatorBuilder:

    • 항목 간의 구분자를 생성하는 역할을 합니다.
    • 이 코드에서는 Gaps.v20라는 위젯이 각 항목 사이에 삽입됩니다. Gaps.v20은 아마도 높이가 20.0SizedBox나 유사한 위젯으로 추측됩니다. 이를 통해 각 코멘트 항목 사이에 공간이 생깁니다.
  3. itemCount:

    • ListView에 표시될 항목의 총 개수를 정의합니다.
    • 이 코드에서는 총 10개의 항목이 표시됩니다.
  4. itemBuilder:

    • 각 항목을 렌더링하는 역할을 합니다.
    • 이 코드에서는 각 항목이 Row 위젯으로 구성되며, 그 안에는 프로필 이미지, 코멘트 내용, 그리고 좋아요 아이콘 및 숫자가 포함됩니다.

요약하면, 이 ListView.separated는 10개의 코멘트 항목을 표시하며, 각 항목은 프로필 이미지, 코멘트 내용, 그리고 좋아요 정보로 구성됩니다. 각 항목 사이에는 Gaps.v20 위젯을 사용하여 공간이 추가됩니다.

ListView.separated는 Flutter 프레임워크의 ListView 위젯 중 하나로, 리스트의 각 항목 사이에 구분자(separator)를 삽입하여 항목들을 표시할 때 유용합니다.

여기에서 이 위젯의 기능과 특성에 대해 자세히 살펴보겠습니다.

ListView.separated

  1. 기본 구성: ListView.separated는 주로 두 개의 필수 콜백인 itemBuilderseparatorBuilder를 요구합니다.

    • itemBuilder: 각 항목을 만드는 데 사용되는 콜백입니다. 이 콜백은 현재의 BuildContext와 항목의 인덱스를 매개변수로 받아 위젯을 반환합니다.
    • separatorBuilder: 항목들 사이에 들어갈 구분자를 만드는 데 사용되는 콜백입니다. 마찬가지로 BuildContext와 인덱스를 매개변수로 받습니다.
  2. 항목 수: itemCount 속성을 사용하여 리스트에 얼마나 많은 항목이 있을지 지정합니다.

  3. 스크롤 방향: 기본적으로 ListView는 세로 방향으로 스크롤됩니다. 하지만 scrollDirection 속성을 사용하여 가로 방향으로 스크롤되게 설정할 수도 있습니다.

  4. 성능: ListView.builder와 마찬가지로 ListView.separated도 항목이 화면에 보일 때만 렌더링됩니다. 따라서 많은 수의 항목을 가진 리스트에 대해 높은 성능을 제공합니다.

예제 코드

ListView.separated(
  itemCount: 10, // 리스트의 항목 수
  itemBuilder: (BuildContext context, int index) {
    return ListTile(
      title: Text('항목 $index'),
    );
  },
  separatorBuilder: (BuildContext context, int index) {
    return Divider(); // 기본적인 구분선 위젯
  },
)

위의 코드에서는 10개의 항목과 각 항목 사이에 Divider라는 구분선을 가진 리스트를 생성합니다.

요약하면, ListView.separated는 항목과 구분자를 따로 정의할 수 있어 목록에 각 항목 사이에 일정한 구분자를 추가하는 데 특히 유용한 위젯입니다.

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:tiktok_clone/constants/gaps.dart';
import 'package:tiktok_clone/constants/sizes.dart';

class VideoComments extends StatefulWidget {
  const VideoComments({super.key});

  
  State<VideoComments> createState() => _VideoCommentsState();
}

class _VideoCommentsState extends State<VideoComments> {
  void _onClosePressed() {
    Navigator.of(context).pop();
  }

  
  Widget build(BuildContext context) {
    return Container(
      clipBehavior: Clip.hardEdge,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(Sizes.size14),
      ),
      child: Scaffold(
        backgroundColor: Colors.grey.shade50,
        appBar: AppBar(
          backgroundColor: Colors.grey.shade50,
          automaticallyImplyLeading: false,
          title: const Text("22796 comments"),
          actions: [
            IconButton(
              onPressed: _onClosePressed,
              icon: const FaIcon(FontAwesomeIcons.xmark),
            ),
          ],
        ),
        body: ListView.separated(
          padding: const EdgeInsets.symmetric(
            vertical: Sizes.size10,
            horizontal: Sizes.size16,
          ),
          separatorBuilder: (context, index) => Gaps.v20,
          itemCount: 10,
          itemBuilder: (context, index) => Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const CircleAvatar(
                radius: 18,
                child: Text("니꼬"),
              ),
              Gaps.h10,
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      '니꼬',
                      style: TextStyle(
                          fontWeight: FontWeight.bold,
                          fontSize: Sizes.size14,
                          color: Colors.grey.shade500),
                    ),
                    Gaps.v3,
                    const Text(
                        "That's not it l've seen the same thing but also in a cave,")
                  ],
                ),
              ),
              Gaps.h10,
              Column(
                children: [
                  FaIcon(
                    FontAwesomeIcons.heart,
                    size: Sizes.size20,
                    color: Colors.grey.shade500,
                  ),
                  Gaps.v2,
                  Text(
                    '52.2K',
                    style: TextStyle(
                      color: Colors.grey.shade500,
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
        bottomNavigationBar: BottomAppBar(
          color: Colors.white,
          child: Row(
            children: [
              CircleAvatar(
                radius: 18,
                backgroundColor: Colors.grey.shade500,
                foregroundColor: Colors.white,
                child: const Text("니꼬"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
ListView.separated(
  padding: const EdgeInsets.symmetric(
    vertical: Sizes.size10,
    horizontal: Sizes.size16,
  ),
  separatorBuilder: (context, index) => Gaps.v20,
  itemCount: 10,
  itemBuilder: (context, index) => Row(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      // ... (코드 생략)
    ],
  ),
)
  1. padding:

    • ListView의 내부 여백을 정의합니다.
    • EdgeInsets.symmetric을 사용하여 세로(vertical) 여백은 Sizes.size10으로, 가로(horizontal) 여백은 Sizes.size16으로 설정되었습니다.
  2. separatorBuilder:

    • 항목 간의 구분자를 생성하는 역할을 합니다.
    • 이 코드에서는 Gaps.v20라는 위젯이 각 항목 사이에 삽입됩니다. Gaps.v20은 아마도 높이가 20.0SizedBox나 유사한 위젯으로 추측됩니다. 이를 통해 각 코멘트 항목 사이에 공간이 생깁니다.
  3. itemCount:

    • ListView에 표시될 항목의 총 개수를 정의합니다.
    • 이 코드에서는 총 10개의 항목이 표시됩니다.
  4. itemBuilder:

    • 각 항목을 렌더링하는 역할을 합니다.
    • 이 코드에서는 각 항목이 Row 위젯으로 구성되며, 그 안에는 프로필 이미지, 코멘트 내용, 그리고 좋아요 아이콘 및 숫자가 포함됩니다.

요약하면, 이 ListView.separated는 10개의 코멘트 항목을 표시하며, 각 항목은 프로필 이미지, 코멘트 내용, 그리고 좋아요 정보로 구성됩니다. 각 항목 사이에는 Gaps.v20 위젯을 사용하여 공간이 추가됩니다.

ListView.separated는 Flutter 프레임워크의 ListView 위젯 중 하나로, 리스트의 각 항목 사이에 구분자(separator)를 삽입하여 항목들을 표시할 때 유용합니다.

여기에서 이 위젯의 기능과 특성에 대해 자세히 살펴보겠습니다.

ListView.separated

  1. 기본 구성: ListView.separated는 주로 두 개의 필수 콜백인 itemBuilderseparatorBuilder를 요구합니다.

    • itemBuilder: 각 항목을 만드는 데 사용되는 콜백입니다. 이 콜백은 현재의 BuildContext와 항목의 인덱스를 매개변수로 받아 위젯을 반환합니다.
    • separatorBuilder: 항목들 사이에 들어갈 구분자를 만드는 데 사용되는 콜백입니다. 마찬가지로 BuildContext와 인덱스를 매개변수로 받습니다.
  2. 항목 수: itemCount 속성을 사용하여 리스트에 얼마나 많은 항목이 있을지 지정합니다.

  3. 스크롤 방향: 기본적으로 ListView는 세로 방향으로 스크롤됩니다. 하지만 scrollDirection 속성을 사용하여 가로 방향으로 스크롤되게 설정할 수도 있습니다.

  4. 성능: ListView.builder와 마찬가지로 ListView.separated도 항목이 화면에 보일 때만 렌더링됩니다. 따라서 많은 수의 항목을 가진 리스트에 대해 높은 성능을 제공합니다.

예제 코드

ListView.separated(
  itemCount: 10, // 리스트의 항목 수
  itemBuilder: (BuildContext context, int index) {
    return ListTile(
      title: Text('항목 $index'),
    );
  },
  separatorBuilder: (BuildContext context, int index) {
    return Divider(); // 기본적인 구분선 위젯
  },
)

위의 코드에서는 10개의 항목과 각 항목 사이에 Divider라는 구분선을 가진 리스트를 생성합니다.

요약하면, ListView.separated는 항목과 구분자를 따로 정의할 수 있어 목록에 각 항목 사이에 일정한 구분자를 추가하는 데 특히 유용한 위젯입니다.

profile
공부하는 개발자

0개의 댓글