flutter(플러터) - 08. ListView(리스트뷰)

JungSik Heo·2026년 4월 29일

flutter

목록 보기
8/23

Flutter ListView (리스트뷰) 정리 + 간단 예제

📌 1. ListView란?

✅ 개념

  • 스크롤 가능한 리스트 UI
  • 여러 아이템을 세로로 나열 + 스크롤 가능

👉 쉽게 말하면
Column + 스크롤 기능 추가된 것


📌 2. 가장 기본 예제

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: ListViewBasicExample(),
    );
  }
}

class ListViewBasicExample extends StatelessWidget {
  const ListViewBasicExample({super.key});

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("ListView 기본")),
      body: ListView(
        children: const [
          ListTile(title: Text("아이템 1")),
          ListTile(title: Text("아이템 2")),
          ListTile(title: Text("아이템 3")),
          ListTile(title: Text("아이템 4")),
        ],
      ),
    );
  }
}

👉 위에서 아래로 스크롤 가능


📌 3. ListView.builder (실무 핵심 ⭐)

👉 데이터 많을 때 필수

class ListViewBuilderExample extends StatelessWidget {
  const ListViewBuilderExample({super.key});

  
  Widget build(BuildContext context) {
    final items = List.generate(20, (index) => "아이템 ${index + 1}");

    return Scaffold(
      appBar: AppBar(title: const Text("ListView.builder")),
      body: ListView.builder(
        itemCount: items.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(items[index]),
          );
        },
      ),
    );
  }
}

📌 4. ListView.separated

👉 아이템 사이 구분선 추가

ListView.separated(
  itemCount: 10,
  itemBuilder: (context, index) {
    return ListTile(title: Text("아이템 $index"));
  },
  separatorBuilder: (context, index) {
    return const Divider();
  },
)
ListViewbuilder
전부 생성필요한 것만 생성
작은 리스트큰 리스트
비효율 가능매우 효율적

📌 5. 가로 ListView

SizedBox(
  height: 100,
  child: ListView(
    scrollDirection: Axis.horizontal,
    children: [
      Container(width: 100, color: Colors.red),
      Container(width: 100, color: Colors.green),
      Container(width: 100, color: Colors.blue),
    ],
  ),
)

👉 좌우 스크롤


📌 6. 실전 예제 (쇼핑앱 느낌)

class ProductListExample extends StatelessWidget {
  const ProductListExample({super.key});

  
  Widget build(BuildContext context) {
    final products = List.generate(10, (i) => "상품 ${i + 1}");

    return Scaffold(
      appBar: AppBar(title: const Text("상품 리스트")),
      body: ListView.builder(
        itemCount: products.length,
        itemBuilder: (context, index) {
          return ListTile(
            leading: Container(
              width: 50,
              height: 50,
              color: Colors.grey,
            ),
            title: Text(products[index]),
            subtitle: const Text("가격: 10,000원"),
            trailing: const Icon(Icons.arrow_forward),
          );
        },
      ),
    );
  }
}

📌 7. 핵심 포인트

타입설명
ListView정적 리스트
ListView.builder동적 리스트 (추천)
ListView.separated구분선 포함

🚨 자주 하는 실수

❌ Column 안에 ListView

Column(
  children: [
    ListView(...) // ❌ 에러 발생
  ],
)

👉 해결 👇

Expanded(
  child: ListView(...),
)

🚀 한 줄 핵심

👉 ListView는 스크롤 가능한 Column이다


🔥 실무 팁

  • 데이터 많으면 무조건 builder
  • 성능 최적화 핵심 위젯
  • API 리스트 출력 기본 구조

https://velog.io/@qazws78941/Flutter-GridView

list_view.dart

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return const MaterialApp(home: ProductListExample());
  }
}

class ProductListExample extends StatelessWidget {
  const ProductListExample({super.key});

  
  Widget build(BuildContext context) {
    final products = List.generate(10, (i) => "상품 ${i + 1}");

    return Scaffold(
      appBar: AppBar(title: const Text("상품 리스트")),
      body: ListView.builder(
        itemCount: products.length,
        itemBuilder: (context, index) {
          // return ListTile(
          //   leading: Container(
          //     width: 50,
          //     height: 50,
          //     color: Colors.grey,
          //   ),
          //   title: Text(products[index]),
          //   subtitle: const Text("가격: 10,000원"),
          //   trailing: const Icon(Icons.arrow_forward),
          // );
          return Container(
            height: 50,
            color: Colors.amber,
            child: Center(child: Text('Entry ${products[index]}')),
          );

        },
      ),
    );
  }
}

class ListViewBasicExample extends StatelessWidget {
  const ListViewBasicExample({super.key});

  
  Widget build(BuildContext context) {
    final items = List.generate(100, (index) => "아이템 ${index + 1}");

    return Scaffold(
      appBar: AppBar(title: const Text("ListView 기본")),
      body: ListView.separated(
        itemCount: 10,
        itemBuilder: (context, index) {
          return ListTile(title: Text("아이템 $index"));
        },
        separatorBuilder: (context, index) {
          return const Divider(
            color: Colors.red,
            thickness: 2,
            height: 30,
            indent: 20,
            endIndent: 20,
          );
        },
      ),
    );
  }
}

// class ListViewBasicExample extends StatelessWidget {
//   const ListViewBasicExample({super.key});
//
//   @override
//   Widget build(BuildContext context) {
//     return Scaffold(
//       appBar: AppBar(title: const Text("ListView 기본")),
//       body: ListView(
//         children: [
//           ListTile(title: Text("아이템 1")),
//           ListTile(title: Text("아이템 2")),
//           ListTile(title: Text("아이템 3")),
//           ListTile(title: Text("아이템 4")),
//           Text("아이템 4"),
//         ],
//       ),
//     );
//   }
// }
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

// MaterialApp 은 StatelessWidget
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'ListView Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomePage(),
    );
  }
}

// Scaffold 화면은 StatefulWidget
class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  late List<String> items;

  @override
  void initState() {
    super.initState();

    items = List.generate(10,(index) => "아이템 $index",);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("ListView.separated"),
      ),

      body: ListView.separated(
        itemCount: items.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(items[index]),
            onTap: () {
              setState(() {
                items[index] =
                "${items[index]} 클릭됨";
              });
            },
          );
        },
        separatorBuilder: (context, index) {
          return const Divider(
            thickness: 1,
          );
        },
      ),
    );
  }
}
profile
쿵스보이(얼짱뮤지션)

0개의 댓글