지금까지는 텍스트 이미지 등 단일 정보를 다뤘다면 이제는 다수 항목을 표시할 수 있는 위젯에 대해 다룹니다.
리스트뷰를 다루는 가장 기본적인 패턴은 정적인 데이터와 동적인 데이터로 구분된다.
리스트뷰에 표시할 데이터가 미리 정해진 경우인 정적 리스트
import 'package:flutter/material.dart';
class ListViewStaticDemo extends StatelessWidget {
static const List<String> _data=[
'Mercury',
'Venus',
'Earth',
'Mars',
'Jupiter',
'Saturn',
'Uranus',
'Neptune'
];
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('ListView'),
centerTitle: true,
),
body: _buildListView(),
);
}
Widget _buildListView(){
return ListView.builder(
itemCount: _data.length,
itemBuilder: (BuildContext _context, int i){
return ListTile(
title: Text(_data[i],
style: TextStyle(fontSize: 23),),
trailing: Icon(Icons.favorite_border),
);
},
);
}
}
static const List<String> _data
String형 리스트인 _data에 행성 이름을 넣었습니다.
ListView.builder
ListView.builder는 리스트뷰를 만들 수 있는 가장 표준적인 방법
빌더는 디자인 패턴의 일종으로 복잡한 기능을 갖는 객체의 생성 과정과 표현 방법을 분리하여 동일 한 생성 절차에서 서로 다른 표현 결과를 만드는 방법을 제공
itemCount: _data.length,
리스트에 표시할 항목의 개수 지정
생략시 무한 데이터를 갖는 리스트뷰로 가정
itemBuilder: (BuildContext _context, int i)
각 행의 항목을 만드는 방법을 지정
ListTile에서 title과 아이콘인 trailing을 사용
데이터의 개수가 사전에 정해지지 않는 동적 데이터 로딩 예제입니다.
휴대폰에 있는 주소록 목록을 표시하는 예제입니다.
주소록 데이터베이스를 접근할 수 있는 contacts_service 패키지를 활용
pubspec.yaml로 가서
다음으로 AndroidManifest.xml로 이동하여 권한을 추가합니다
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>```
```dart
import 'package:contacts_service/contacts_service.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
class ListViewStaticDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('ListView'),
centerTitle: true,
),
body: ContactListPage()
);
}
}
class ContactListPage extends StatefulWidget {
@override
_ContactListPageState createState() => _ContactListPageState();
}
class _ContactListPageState extends State<ContactListPage> {
Iterable<Contact> _contacts;
@override
void initState() {
super.initState();
_checkPermissions();
}
_checkPermissions()async{
await PermissionHandler().requestPermissions([PermissionGroup.contacts]);
refreshContacts();
}
refreshContacts()async{
Iterable<Contact> contacts=
await ContactsService.getContacts(withThumbnails: false);
setState(() {
_contacts=contacts;
});
}
@override
Widget build(BuildContext context) {
return _contacts !=null
? ListView.builder(itemCount: _contacts.length,itemBuilder: _buildRow)
: Center(child: CircularProgressIndicator());
}
Widget _buildRow(BuildContext context,int i){
Contact c=_contacts.elementAt(i);
return ListTile(
leading: (c.avatar !=null && c.avatar.length>0)
? CircleAvatar(backgroundImage: MemoryImage(c.avatar))
: CircleAvatar(child: Text(c.initials()),),
title: Text(c.displayName ?? " "),
);
}
}
_checkPermissions()
먼저 권한을 확인하는 _checkPermissions메서드를 호출합니다
이 메서드는 사용자의 선택을 기다려야 하므로 async 키워드가 필요합니다
권한을 획득하면 refreshContacts() async 메서드 호출
refreshContacts() async
refreshContacts() 메서드는 비동기로 contacts_service 패키지에 있는 ContactService.getContacts() 메서드를 호출합니다.
withThumbnails 속성을 false로 하면 썸네일을 로딩하지 않기 때문에 속도가 빠릅니다
로딩이 완료되면 setState() 메서드를 호출하여 _contacts변수를 갱신합니다
_buildRow
ListTile 위젯을 사용하여 리스트의 각 행을 표시합니다
leading 속성에 사진을 표시하거나 없으면 이니셜을 표시합니다.
결과
들고.