본문 바로가기
Flutter

[Flutter00] Flutter 기초다지기3 _ List

by JINJINC 2025. 1. 8.
728x90
반응형

ListView 사용법과 주요 property

  • 가장 일반적으로 사용되는 스크롤 위젯
  • ListView는 주로 다음과 같은 방식으로 사용
    • 일반적인 ListView를 명시적으로 호출하고 children 전달하는 방법 (적은 데이터에 사용시 용이함)
    • ListView.builder를 사용하여 동적으로 호출
    • ListView.separated는 ListView.builder 기능에 구분선 사용 가능
  • 주요 property
    • reverse: true이면 bottom에서부터 리스트 표시
    • padding: 리스트 아이템 간격 (EdgeInsets로 적용)
    • itemCount: 동적 리스트 아이템 개수 (ListView.builder/ListView.separated에서 사용 가능)
    • itemBuilder: 각 동적 리스트 아이템 정의 (ListView.builder/ListView.separated에서 사용 가능)
    • physics: 스크롤 방식 설정

리스트 타일 위젯을 사용

 

import 'package:flutter/material.dart';

// ListView와 ListTile 위젯을 살펴보자
void main() {
  runApp(MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Scaffold(
          body: ListView(
            children: [
              ListTile(
                leading: CircleAvatar(
                  backgroundColor: Colors.amber,
                  child: Text(
                    '1',
                    style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
                  ),
                ),
                title: Text(
                  'item1',
                  style: TextStyle(color: Colors.black),
                ),
                subtitle: Text('item sub....'),
                trailing: IconButton(
                    onPressed: () => {print('버튼 눌렀다.')},
                    icon: Icon(Icons.more_horiz)),
              ),
              ListTile(
                leading: CircleAvatar(
                  backgroundColor: Colors.amber,
                  child: Text(
                    '1',
                    style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
                  ),
                ),
                title: Text(
                  'item1',
                  style: TextStyle(color: Colors.black),
                ),
                subtitle: Text('item sub....'),
                trailing: IconButton(
                    onPressed: () => {print('버튼 눌렀다.')},
                    icon: Icon(Icons.more_horiz)),
              )
            ],
          ),
        ));
  }
}

 

list-2
import 'package:flutter/material.dart';

// ListView와 ListTile 위젯을 살펴보자
void main() {
  runApp(MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Scaffold(
          body: ListView.builder(
            itemCount: 20,
            itemBuilder: (context, index) {
              return ListTile(
                leading: CircleAvatar(
                  backgroundColor: Colors.amber,
                  child: Text('${index + 1}'),
                ),
                title: Text('Item ${index + 1}'),
                subtitle: Text('Item sub ${index + 1}'),
                trailing: IconButton(
                    onPressed: () {
                      print('${index + 1} 버튼 눌렀다.');
                    },
                    icon: Icon(Icons.more_horiz)),
              );
            },
          ),
        ));
  }
}

 

GridView 위젯

  • 리스트 뷰와 마찬가지로 항목을 나열하는 위젯이지만, 리스트 뷰와 달리 한 줄에 여러 개를 함께 나열할 수 있음 (그리드 형태)
  • 리스트 뷰와 마찬가지로 그리드뷰도 GridView.builder() 생성자를 제공하며,
    • itemCount, itemBuilder 속성을 통해 항목의 개수와 위젯을 지정
    • gridDelegate 속성을 설정해야 함
      • 이 속성에는 SliverGridDelegateWithFixedCrossAxisCount 객체를 지정해줘야 함
      • 해당 객체에서 crossAxisCount 값이 한 줄에 함께 나와야 하는 항목의 개수임
      • 그리드 두 방향을 설정하지 않으면, crossAxisCount는 가로를 가리킴
  • 리스트 뷰와 마찬가지로 항목을 나열하는 위젯이지만, 리스트 뷰와 달리 한 줄에 여러 개를 함께 나열할 수 있음 (그리드 형태)
  • 리스트 뷰와 마찬가지로 그리드뷰도 GridView.builder() 생성자를 제공하며,
    • itemCount, itemBuilder 속성을 통해 항목의 개수와 위젯을 지정
    • gridDelegate 속성을 설정해야 함
      • 이 속성에는 SliverGridDelegateWithFixedCrossAxisCount 객체를 지정해줘야 함
      • 해당 객체에서 crossAxisCount 값이 한 줄에 함께 나와야 하는 항목의 개수임
      • 그리드 두 방향을 설정하지 않으면, crossAxisCount는 가로를 가리킴
  • 참고: scrollDirection 속성에 Axis.horizontal을 설정하면, crossAxisCount는 세로 방향을 가리킴

 

그리드 뷰 연습
import 'package:flutter/material.dart';

// ListView와 ListTile 위젯을 살펴보자
void main() {
  runApp(MyApp());
}

class PocketMon {
  final String imagename;
  final String name;
  final int power;

  PocketMon(this.imagename, this.name, this.power);
}

class MyApp extends StatelessWidget {
  final List<PocketMon> pocketmons = [
    PocketMon('메타몽.jpg', '메타몽', 10),
    PocketMon('뮤츠.jpg', '뮤츠', 100),
    PocketMon('잠만보.jpg', '잠만보', 1),
    PocketMon('파이리.png', '파이리', 80),
    PocketMon('메타몽.jpg', '메타몽', 10),
    PocketMon('뮤츠.jpg', '뮤츠', 100),
    PocketMon('잠만보.jpg', '잠만보', 1),
    PocketMon('파이리.png', '파이리', 80),
    PocketMon('메타몽.jpg', '메타몽', 10),
    PocketMon('뮤츠.jpg', '뮤츠', 100),
    PocketMon('잠만보.jpg', '잠만보', 1),
    PocketMon('파이리.png', '파이리', 80),
    PocketMon('메타몽.jpg', '메타몽', 10),
    PocketMon('뮤츠.jpg', '뮤츠', 100),
    PocketMon('잠만보.jpg', '잠만보', 1),
    PocketMon('파이리.png', '파이리', 80),
    PocketMon('메타몽.jpg', '메타몽', 10),
    PocketMon('뮤츠.jpg', '뮤츠', 100),
    PocketMon('잠만보.jpg', '잠만보', 1),
    PocketMon('파이리.png', '파이리', 80),
    PocketMon('메타몽.jpg', '메타몽', 10),
    PocketMon('뮤츠.jpg', '뮤츠', 100),
    PocketMon('잠만보.jpg', '잠만보', 1),
    PocketMon('파이리.png', '파이리', 80),
  ];

  MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: GridView.builder(
          scrollDirection: Axis.vertical,
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 3,
            crossAxisSpacing: 10.0,
            mainAxisSpacing: 10.0,
            childAspectRatio: 2 / 3,
          ),
          itemBuilder: (context, index) {
            return _innerContainer(
              pocketmons[index].imagename,
              pocketmons[index].name,
              pocketmons[index].power,
            );
          },
          itemCount: 20,
        ),
      ),
    );
  }

  Widget _innerContainer(String name, String text, int power) {
    return LayoutBuilder(
      builder: (context, constraints) {
        double parentWidth = constraints.maxWidth;
        return Container(
          decoration: BoxDecoration(
              color: Colors.white,
              border: Border.all(
                color: Colors.amber,
                width: 4,
              )),
          child: Center(
              child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Image.asset(
                width: 150,
                height: 180,
                'assets/images/${name}',
                fit: BoxFit.contain,
              ),
              SizedBox(
                height: 20,
              ),
              _builderNameContainer(text, power, parentWidth),
              // Text(
              //   ' ${text}',
              //   style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
              // ),
              // Text('Power : ${power}'),
            ],
          )),
        );
      },
    );
  }

  Widget _builderNameContainer(String text, int power, double parentWidth) {
    return Container(
      width: parentWidth,
      color: Colors.amber,
      child: Column(children: [
        Text(
          ' ${text}',
          style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
        ),
        Text('Power : ${power}'),
      ]),
    );
  }
}

 

 

PageView 위젯

  • 스와이프 이벤트에 반응하여 항목을 보여주는 위젯
  • PageController의 initialPage로 처음 보일 페이지를 설정할 수 있고, viewportFraction으로 현재 페이지가 화면에 차지하는 비율도 설정 가능
    • 예: viewportFraction: 0.7이면 현재 페이지가 화면에 70%, 나머지 30%가 이전과 다음 페이지가 살짝 보이게 됨
  • PageController 객체를 PageView의 controller 속성에 적용하여, PageController 설정을 반영시킬 수 있음
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: SafeArea(
        child: Scaffold(
          appBar: AppBar(
            backgroundColor: Colors.white,
            elevation: 1.0,
            title: Text('Page View'),
          ),
          body: PageView(
            controller: PageController(
              initialPage: 2,
              viewportFraction: 0.5,
            ),
            children: [
              Container(
                margin: EdgeInsets.all(0.0),
                color: Colors.red,
              ),
              Container(
                margin: EdgeInsets.all(0.0),
                color: Colors.lime,
              ),
              Container(
                margin: EdgeInsets.all(0.0),
                color: Colors.deepPurpleAccent,
              )
            ],
          ),
        ),
      ),
    );
  }
}
728x90
반응형

'Flutter' 카테고리의 다른 글

[flutter19] LoginApp 만들기  (0) 2025.01.13
[Flutter00]플러터 기본기 다지기2  (0) 2025.01.08
[Flutter00] 플러터의 기본개념 다지기1  (0) 2025.01.08

댓글