20. 플러터 : 탭바 기본 (아이콘 + 제목)

탭바와 화면 중앙에 아이콘을 추가했더니
앱의 품질이 매우 좋아진 것처럼 느껴지는 것은 나만의 착각일까?



역시 주석을 꼼꼼하게 달았다.
이번 코드에서 주의 깊게 볼 것은 아이콘 사용은 아니다.
그건 너무 쉬우니까.

구조체 같은 Choice 클래스를 만들었고
왜 만들었는지에 대한 이해를 할 수 있다면 얼마나 좋을까?
주석에 있는 것처럼 단순하게 두 군데에서 사용하기 위해서라고 생각할까?

import 'package:flutter/material.dart';

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

// 아이콘과 제목을 함께 보여주기 위해 데이터만 포함하는 구조체 스타일의 클래스 생성
class Choice {
Choice(this.text, this.icon);
final String text;
final IconData icon;

// 매개변수를 전달할 때 {}가 있다면 매개변수 이름을 생략할 수 없다.
// Choice({this.title, this.icon});
}

class TabBarSample extends StatelessWidget {
// 탭바와 탭바뷰 양쪽에서 사용하기 위한 공통 데이터 리스트.
// Choice 생성자에 {}를 사용하지 않았기 때문에 매개변수 이름이 없다.
final choices = [
Choice('PLANE', Icons.flight),
Choice('CAR', Icons.directions_car),
Choice('BIKE', Icons.directions_bike),
Choice('BOAT', Icons.directions_boat),
Choice('BUS', Icons.directions_bus),
Choice('TRAIN', Icons.directions_railway),
Choice('WALK', Icons.directions_walk),
];

@override
Widget build(BuildContext context) {
return DefaultTabController(
length: choices.length,
child: Scaffold(
appBar: AppBar(
title: Text('교통 수단'),
bottom: TabBar(
tabs: choices.map((Choice choice) {
return Tab(
text: choice.text,
icon: Icon(choice.icon), // 이전 코드와 다른 부분
);
}).toList(),
isScrollable: true,
),
),
body: TabBarView(
// map과 toList 함수를 연결해서 화면 리스트 전달
children: choices.map((Choice choice) {
// 문자열과 아이콘을 모두 포함하는 위젯 객체 생성
// 이전 코드에서는 Text 위젯 하나만 사용했었다. 코드가 많아 클래스로 분리.
return ChoiceCard(
// 생성자에서 {}를 사용했기 때문에 text와 icon 매개변수 이름 사용 필수
text: choice.text,
icon: choice.icon, // 이전 코드와 다른 부분
);
}).toList(),
),
),
);
}
}

class ChoiceCard extends StatelessWidget {
// 매개변수 주변에 {}가 있기 때문에 text와 icon이라는 매개변수 이름을 함께 사용해야 한다.
const ChoiceCard({Key key, this.text, this.icon}) : super(key: key);

final String text;
final IconData icon;

@override
Widget build(BuildContext context) {
// 아이콘과 텍스트 양쪽에서 사용하기 위해 별도 변수로 처리
final TextStyle textStyle = Theme.of(context).textTheme.display3;
return Card(
child: Column(
children: <Widget>[
// 아이콘이 위쪽, 문자열이 아래쪽.
Icon(icon, size: 128.0, color: textStyle.color),
Text(text, style: textStyle),
],
mainAxisAlignment: MainAxisAlignment.center,
),
color: Colors.green,
margin: EdgeInsets.all(12),
);
}
}


클래스 없이 만들 수 있는 방법이 있지 않을까?
일단 클래스와 같은, 크기가 작아도 클래스니까 코드가 복잡해 진다.
클래스를 없애보자!

고생 엄청 했다.
몇 시간 코딩하고 나서 알았다.
생각 좀 하고 코딩했어야 하는데.. 일단 코딩하고 보는 성격이라..
우재야! 아빠가 급한 성격이니?

문제는 Card 클래스를 사용해서 화면 중앙에 탭의 내용을 다시 한번 출력하려는 것이다.
그러니 두 군데에 나올 수밖에 없다.
보통은 전혀 그럴 일이 없기 때문에 실제 상황에서는 Choice 같은 클래스는 사용하지 않을 것이다.
항상 그랬기 때문에 미처 감지하지 못했다. 늘 하던 방식으로 생각하는 바람에.

Card 클래스는 아래 그림과 같은
Material 클래스에서 제공하는 많지 않은 데이터를 보여주는 위젯이다.


이번 예제는 플러터에서 가져왔다.
좋은 예제들이 많으니까 꼭 둘러보기 바란다.