Foggy day
[Flutter] GridView - 사용법 본문
이번 포스팅에서는 GridView 위젯에 대해 알아보겠습니다. GridView는 ListView와 동일한 특성들이 많습니다. 그래서 ListView에는 없는 내용들만 다루겠습니다. 중복된 내용들은 ListView 포스팅을 참고해 주시기 바랍니다.
https://jinhan38.tistory.com/134
1. 기본 사용법(GridView.count)
2. SliverGridDelegate
3. GridView.extent
4. GridView.builder
1. 기본 사용법(GridView.count)
GridView는 한 가지 함수를 제외하고는 모두 SliverGridDelegate를 필요로합니다. 1번에서는 SliverGridDelegate 없이 사용해 보고 2번부터 SliverGridDelegate를 배운 후 다른 GridView들을 사용해 보겠습니다.
GridView.count를 사용하면 SliverGridDelegate를 사용하지 않고 GirdView를 만들 수 있습니다.
crossAxisCount 항목에 기준축(main)과 교차되는(cross) 축에 몇 개의 타일을 사용할지 입력합니다.
기준 축은 scrollDirection 특성으로 변경할 수 있습니다.
Widget _gridViewCount() {
return GridView.count(
scrollDirection: Axis.vertical,
crossAxisCount: 4,
children: [
..._listItem(),
],
);
}
2. SliverGridDelegate
SliverGridDelegate는 GridView에 들어가는 타일들의 레이아웃을 계산합니다. SliverGridDelegate는 추상 클래스이기 때문에 실제로는 SliverGridDelegateWithFixedCrossAxisCount, SliverGridDelegateWithMaxCrossAxisExtent 두 클래스를 사용합니다.
- SliverGridDelegateWithFixedCrossAxisCount : 기준 축과 교차되는 축의 개수를 결정합니다. 세로 스크롤이라면 가로로 몇 개의 타일이 들어갈지 설정할 수 있습니다.
crossAxisCount : cross되는 축에 들어갈 타일의 개수
crossAxisSpacing : cross되는 축의 타일들 사이의 간격
mainAxisSpacing : 기준 축의 타일들 사이의 간격
childAspectRatio : 기준 축과 크로스되는크로스 되는 축의 비율. 2를 입력하면 기준축의 사이즈보다 크로스 되는 축의 사이즈가 2배. (ex. 기준축이 세로일 경우, 가로 사이즈가 세로 사이즈의 2배)
mainAxisExtent : main축(기준축)의 사이즈(mainAxisExtent를 입력하면 childAspectRatio는 무시됩니다.)
Widget _body() {
return GridView(
gridDelegate: _sliverGridDelegate(),
children: [
..._listItem(),
],
);
}
SliverGridDelegate _sliverGridDelegate() {
return const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 10,
mainAxisSpacing: 30,
mainAxisExtent: 150,
// childAspectRatio: 2,
);
}
- SliverGridDelegateWithMaxCrossAxisExtent : main 축과 cross 된 축의 최대 사이즈를 입력해서 타일의 레이아웃을 계산합니다.
maxCrossAxisExtent : cross축 한 개 타일의 최대 사이즈를 지정합니다.
만약에 가로 사이즈가 500이고, maxCrossAxisExtent를 150으로 입력한다면 125 넓이의 타일 4개를 만듭니다.
가로 사이즈가 300이고, maxCrossAxisExtent를 100~140사이로 입력한다면 3개의 타일이 만들어집니다.
가로 사이즈가 300이고, maxCrossAxisExtent를 150으로 입력한다면 2개의 타일이 만들어집니다.
maxCrossAxisExtent에 입력한 값으로 타일 사이즈를 지정하는 것이 아닙니다. 가로넓이와 maxCrossAxisExten를 계산해서 만들 수 있는 최대한의 타일 크기로 만들어집니다.
mainAxisExtent : 기준축의 사이즈
mainAxisSpacing : 기준축 타일의 간격
crossAxisSpacing : 교차축 타일의 간격
Widget _body() {
return SizedBox(
width: 300,
child: GridView(
gridDelegate: _sliverGridDelegate(),
children: [
..._listItem(),
],
),
);
}
SliverGridDelegate _sliverGridDelegate() {
return const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 140,
mainAxisExtent: 200,
mainAxisSpacing: 10,
// crossAxisSpacing: 10,
);
}
3. GridView.extent
GridView.extent는 2번에서 다룬 SliverGridDelegateWithMaxCrossAxisExtent를 확장함수로 구현해 놓은 함수입니다. maxCrossAxisExtent값을 받아서 가로 축의 개수를 설정할 수 있습니다.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("GridViewScreen"),
),
body: _gridViewExtent(),
);
}
Widget _gridViewExtent() {
return GridView.extent(
maxCrossAxisExtent: 150,
children: [
..._listItem(),
],
);
}
4. GridView.builder
GridView.builder는 ListView.builder와 같은 형태입니다. itemBuilder 함수를 각각의 타일들을 만들 수 있습니다.
그리고 itemCount를 꼭 입력해야 합니다. 그렇지 않으면 몇개의 자식 위젯들을 생성할지 알 수 없기 때문입니다.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("GridViewScreen"),
),
body: _gridViewBuilder(),
);
}
Widget _gridViewBuilder() {
return GridView.builder(
itemCount: _listItem().length,
gridDelegate: _sliverGridDelegate(),
itemBuilder: (context, index) {
return _listItem()[index];
},
);
}
itemBuilder함수의 형태.
Widget을 반환하여 context와 index를 전달합니다.
Widget? Function(BuildContext context, int index);
Full code
import 'dart:math';
import 'package:flutter/material.dart';
class GridViewScreen extends StatefulWidget {
const GridViewScreen({Key? key}) : super(key: key);
@override
State<GridViewScreen> createState() => _GridViewScreenState();
}
class _GridViewScreenState extends State<GridViewScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("GridViewScreen"),
),
body: _gridViewBuilder(),
);
}
Widget _gridViewCount() {
return GridView.count(
scrollDirection: Axis.vertical,
crossAxisCount: 4,
children: [
..._listItem(),
],
);
}
Widget _gridViewExtent() {
return GridView.extent(
maxCrossAxisExtent: 150,
children: [
..._listItem(),
],
);
}
Widget _gridViewBuilder() {
return GridView.builder(
itemCount: _listItem().length,
gridDelegate: _sliverGridDelegate(),
itemBuilder: (context, index) {
return _listItem()[index];
},
);
}
Widget _body() {
return GridView(
gridDelegate: _sliverGridDelegate(),
children: [
..._listItem(),
],
);
}
SliverGridDelegate _sliverGridDelegate() {
// return const SliverGridDelegateWithMaxCrossAxisExtent(
// maxCrossAxisExtent: 140,
// mainAxisExtent: 200,
// mainAxisSpacing: 10,
// // crossAxisSpacing: 10,
// );
return const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 10,
mainAxisSpacing: 30,
mainAxisExtent: 150,
// childAspectRatio: 2,
);
}
List<Widget> _listItem() {
List<Widget> widgets = [];
for (int i = 0; i < 30; i++) {
widgets.add(
Container(
color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
),
);
}
return widgets;
}
}
'Flutter > Flutter widget' 카테고리의 다른 글
[Flutter] Stack Widget - 사용법 (0) | 2023.03.26 |
---|---|
[Flutter] How Flutter renders Widgets? - Flutter가 위젯을 그리는 방법 (0) | 2023.03.24 |
[Flutter] ListView - 사용법 (2) | 2023.03.23 |
[Flutter] SingleChildScrollView - 사용법 (0) | 2023.03.22 |
[Flutter] Image Widget - 사용법 (0) | 2023.03.22 |