Tab View 만들기(2) - PageView
Tab View 만들기(3) - Custom 1탄
Tab View 만들기(4) - Custom 2탄
이번 글 부터 Tab View를 만드는 방법에 대해서 작성하도록 하겠다.
Tab View는 앱을 만들다 보면 거의 무조건 사용을 해야하는 위젯 중에 하나라고 볼 수 있는데, Tab View가 조금의 다른 UI 구조로 개발을 하려고 하면 잘 안되서 결국 직접 만들어 쓰는 경우도 있었다.
Tab View를 가장 쉽고 간단하게 사용하는 방법은 바로 Flutter에서 기본으로 제공해주는 TabbarView 위젯이다.
해당 위젯은 DefaultTabController위젯에 몇 개의 탭을 생성할지에 대한 length만 넣어주고 아래에 tab/tabbar를 생성한 개수만큼 넣어주면 자동으로 탭 스크롤, 인디케이터 스크롤 등을 바로 만들어 주는 위젯이다.
여기서는 정말 간단한 UI구조로 3개의 탭을 구성하여 첫 번째 탭에는 ListView를 넣고 두 번째 탭에는 GridView 그리고 마지막 탭에는 간단한 컨테이너 박스를 넣는 UI를 만들었다.
복잡한 UI구조나 구현하고 싶은 Tab View 구조가 있다면 댓글 달아주세요. 만들어서 따로 글을 작성하도록 하겠습니다.
Tab을 사용하기 위해서는 TabBar와 TabBarView를 연결을 해주어야 하는데, 방법이 두 개가 있다. 아래 처럼 DefaultTabController로 간단하게 사용하는 방법이 있고 TabController를 사용하는 방법이 있는데, TabController는 vsync를 연결하여야 하므로 기본 위젯에서는 사용할 수 없고 Ticker 위젯을 믹스인 하여야 하는데, TabController 방식은 다음 글에서 어떻게 사용하는지 다루고 있기에 다음 글을 참고 하면된다.
return DefaultTabController(
length: 3,
child: Scaffold(
...
));
body 안에 Column위젯으로 만들어 준뒤 먼저 TabBar를 만들어 보자.
TabBar는 자식들로 Tab을 넣어주어야 하는데 반드시 위에서 생성한 length의 갯수와 맞아야 한다. 다르다면 바로 에러나요..
Tab은 아래와 같이 생성한 뒤 TabBar에서 제공하는 옵션 값으로 UI를 변경할 수 있다. 텍스트 스타일 부터 인디케이터 스타일 까지 변경할 수 있는데, 여기서는 인디케이터의 두께만 3으로 해줬다.
const TabBar(
indicatorColor: Colors.white,
labelStyle: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 20),
indicatorWeight: 3,
tabs: [
Tab(
text: 'List',
height: 50,
),
Tab(
text: 'Grid',
height: 50,
),
Tab(
text: 'Box',
height: 50,
),
]),
Column위젯으로 TabBar와 TabBarView를 넣어주면 반드시 Expanded 확장 위젯을 사용하여 나머지 공간을 TabBarView 위젯들이 확장될 수 있도록 해주어야 하고 아니면 사이즈 값을 넣어 주어야 한다.
참고로 여기서는 간단하게 구현한거라 Nested Sliver 위젯을 사용하지 않았는데, 보통 Tab View를 만들 때는 Sliver 위젯으로 만드는 경우가 많다.
Expanded(
child: TabBarView(
children: [
...
],
)
),
TabBarView에 넣어야 하는 3개의 View이다. 여기서 중요한 점은 View안에 스크롤이 가능한 위젯을 넣게 되고, Tab 간 이동이 발생할 때 스크롤 포지션이 초기화 되게 되는데, 이럴 때 스크롤 뷰의 key 옵션을 활용하여 스크롤의 포지션 값을 저장해주는 방식으로 개발을 하면 탭 간 이동시에도 스크롤은 포지션을 유지할 수 있게 된다.
ListView.builder(
key: const PageStorageKey("LIST_VIEW"),
itemCount: 1000,
itemBuilder: (context, index) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 12),
width: MediaQuery.of(context).size.width,
child: Center(
child: Text(
"List View $index",
style: TextStyle(
fontSize: 16,
color: Colors.accents[index % 15],
fontWeight: FontWeight.bold),
),
),
);
}),
GridView.builder(
key: const PageStorageKey("GRID_VIEW"),
itemCount: 1000,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
itemBuilder: ((context, index) {
List<int> _number = [
Random().nextInt(255),
Random().nextInt(255),
Random().nextInt(255)
];
return Container(
color: Color.fromRGBO(
_number[0], _number[1], _number[2], 1),
child: Center(
child: Text(
"Grid View $index",
style: const TextStyle(
fontSize: 16,
color: Colors.white,
fontWeight: FontWeight.bold),
)),
);
})),
Container(
width: 10,
color: const Color.fromRGBO(91, 91, 91, 1),
child: const Center(
child: Text(
'Box',
style: TextStyle(
color: Colors.white,
fontSize: 56,
fontWeight: FontWeight.bold),
),
),
),
TabBar/TabBarView는 기본적으로 이러한 기능을 제공해주는 위젯이라 Tab View를 만들기 가장 쉽다는 장점이 있지만 그 만큼 커스텀해서 사용하기에 조금 까다로운 위젯이다.
다음 글에서는 PageView를 사용하여 Tab View를 구현해보도록 하겠다.