24. 플러터 : 목록 보기 (화면 전환)

여기까지만 할까?

왼쪽 그림에서 목록을 보여주고, 하나를 선택하면 오른쪽 그림으로 넘어가는거야.
상단 네비게이션바의 뒤로(<- 화살표) 버튼을 누르면 다시 왼쪽 그림이 나타나지.

왼쪽 그림에서 가운데 흐린 파랑은
출력 결과가 정확하게 가운데 표시된다는 것을 알려줘.
직접 해보면 가운데 오게 하는 것이 잘 안되거든.
왼쪽 그림에서는 표시가 잘 나진 않지만,
조금 스크롤되니까 위아래로 꼭 움직여 봐야 해.
안드로이드 디바이스를 어떤 걸 선택했느냐에 따라 화면 안에 전부 출력될 수도 있는데..
그러면 스크롤은 당연히 안 되겠지?



이번 코드에서 중요한 점은
첫 번째로 데이터 클래스를 만들어서 리스트를 생성하고 상세보기 클래스에 전달하는 방법.
두 번째로 위젯이 많이 중첩돼서 헷갈리지만, 출력물이 화면 가운데 오게 하는 방법.
세 번째로 커스텀 셀(custom cell)이라고 부르는 리스트뷰 항목을 원하는 대로 구성하는 방법.

import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(home: MyApp()));

// 구조체 스타일의 클래스. 상세보기로 데이터를 넘길 목적으로 생성.
class PageInfo {
PageInfo(this.image, this.title, this.group);

String image; // 사진 경로
String title; // 본문 설명
String group; // 지역 이름
}

class MyApp extends StatelessWidget {
final infos = [
PageInfo('images/family_1.jpg', '서핑 후의 달콤한 휴식. 아이서프 샵', '설악'),
PageInfo('images/family_2.jpg', '보드가 서퍼보다 크다!', '설악'),
PageInfo('images/family_3.jpg', '우재와 서진, 잘 생겼다!', '설악'),
PageInfo('images/family_4.jpg', '따뜻한 적이 없던 스키장. 장갑이 필요해!', '지산'),
];

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('새로운 기억들')),
// itemExtent 옵션으로 항목 높이 설정
// map 함수로 infos에 들어있는 개수만큼 ListTile 객체 생성 (makeRowItem)
body: ListView(
itemExtent: 120,
children: infos.map((info) => makeRowItem(context, info)).toList(),
),
);
}

Widget makeRowItem(BuildContext ctx, PageInfo info) {
return Center(child: Container(
color: Colors.lightBlue[100], // 출력물이 항목 가운데 오는지 확인하기 위한 용도
child: ListTile(
// 셀의 왼쪽 영역. 오른쪽을 가리키는 trailing도 있지만, 여기서는 사용 안함
leading: Image.asset(
info.image, width: 100, height: 100, fit: BoxFit.cover),
// 본문 영역에 Row나 Column 위젯을 통한 여러 개의 위젯 전달 가능
title: Row(
children: <Widget>[
Expanded( // 자식 위젯이 나머지 전체를 차지하도록 확장
child: Text(
info.title,
style: TextStyle(fontSize: 19, color: Colors.blueGrey)),
),
Container( // 답답해 보이지 않도록 패딩을 주기 위해 사용
child: Text(
info.group,
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.black54)),
padding: EdgeInsets.only(left: 12.0, right: 12.0),
),
],
),
// 특정 셀을 선택하면 다음 화면으로 현재 셀의 데이터 전달하면서 이동
onTap: () {
Navigator.push(ctx,
MaterialPageRoute<void>(builder: (BuildContext context) => Detail(info: info))
);
},
),
),
);
}
}

// 상세보기 화면 클래스
// 실제로는 더 많은 데이터가 전달되어야 하지만, 여기서는 3가지만 사용.
class Detail extends StatelessWidget {
// key는 부모 클래스에서 사용하는 기본 옵션
Detail({Key key, this.info}) : super(key: key);
final PageInfo info;

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(info.group)),
body: SingleChildScrollView( // 없으면, 화면을 벗어났을 때 볼 수 없음 (스크롤 지원)
child: Column(
children: <Widget>[
Container(
child: Center(
child: Text(
info.title,
style: TextStyle(fontSize: 21.0, color: Colors.black87),
),
),
padding: EdgeInsets.all(20.0),
),
Container(
child: Image.asset(info.image, fit: BoxFit.contain),
padding: EdgeInsets.all(10.0),
),
],
),
),
);
}
}


다 했어?
그러면 간단한 프로젝트를 시작해야 할테고
잘 안되는 것들은 꼭 질문하기.
명심할 것은 바로 질문해서는 안 되고 조금이라도 고민한 후에 질문하기.

우재가 시행착오를 잘 이겨내고
그럴듯한 스마트폰 앱으로 친구들한테 자랑할 날을 기다리면서.
아빠가!!