[Flutter] スワイプ&スクロール可能なタブを実装してみた

2022.04.05

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部IoT事業部の高橋雄大です。

前回のボトムナビゲーションに続いて、Flutterにおけるタブの実装方法について調べてみました。画面上部のタブは手が届きにくいため、画面をスワイプ(スライド)させることでタブの切替ができるようにしたいと思います。また、項目が多いタブでは横にスクロールさせることで、画面からはみ出しているタブを表示します。

本記事のゴール

画面上部にスワイプとスクロールが可能なタブを実装します。

Flutterタブメニュー

ボトムナビゲーションの実装は前回の記事を参考にしてください。

環境情報

項目 内容
OS macOS Monterey 12.3 (21E230)
Visual Studio Code 1.66.0
Xcode 13.3 (13E113)
Flutter 2.10.4
Dart 2.16.2

タブを実装

DefaultTabControllerTabBarで画面上部にタブを実装します。

lib/src/screens/home.dart

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      initialIndex: 0, // 最初に表示するタブ
      length: 3, // タブの数
      child: Scaffold(
        appBar: AppBar(
          title: const Text('ホーム'),
          bottom: const TabBar(
            tabs: <Widget>[
              Tab(text: '野球'),
              Tab(text: 'サッカー'),
              Tab(text: 'テニス'),
            ],
          ),
        ),
        body: const TabBarView(
          children: <Widget>[
            Center(
              child: Text('野球', style: TextStyle(fontSize: 32.0)),
            ),
            Center(
              child: Text('サッカー', style: TextStyle(fontSize: 32.0)),
            ),
            Center(
              child: Text('テニス', style: TextStyle(fontSize: 32.0)),
            ),
          ],
        ),
      ),
    );
  }
}

クリックかスワイプで切替ができるタブが追加されました。

Flutterタブメニュー

タブをアイコンにすることも可能です。

lib/src/screens/home.dart

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      initialIndex: 0, // 最初に表示するタブ
      length: 3, // タブの数
      child: Scaffold(
        appBar: AppBar(
          title: const Text('ホーム'),
          bottom: const TabBar(
            tabs: <Widget>[
              Tab(icon: Icon(Icons.sports_baseball)),
              Tab(icon: Icon(Icons.sports_soccer)),
              Tab(icon: Icon(Icons.sports_tennis)),
            ],
          ),
        ),
        body: const TabBarView(
          children: <Widget>[
            Center(
              child: Text('野球', style: TextStyle(fontSize: 32.0)),
            ),
            Center(
              child: Text('サッカー', style: TextStyle(fontSize: 32.0)),
            ),
            Center(
              child: Text('テニス', style: TextStyle(fontSize: 32.0)),
            ),
          ],
        ),
      ),
    );
  }
}

タブにアイコンが表示されました。

Flutterタブメニュー

項目が多いタブをスクロールできるようにしてみます。

lib/src/screens/home.dart

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      initialIndex: 0, // 最初に表示するタブ
      length: 8, // タブの数
      child: Scaffold(
        appBar: AppBar(
          title: const Text('ホーム'),
          bottom: const TabBar(
            isScrollable: true, // スクロールを有効化
            tabs: <Widget>[
              Tab(text: '野球'),
              Tab(text: 'サッカー'),
              Tab(text: 'テニス'),
              Tab(text: 'バスケ'),
              Tab(text: '剣道'),
              Tab(text: '柔道'),
              Tab(text: '水泳'),
              Tab(text: '卓球'),
            ],
          ),
        ),
        body: const TabBarView(
          children: <Widget>[
            Center(
              child: Text('野球', style: TextStyle(fontSize: 32.0)),
            ),
            Center(
              child: Text('サッカー', style: TextStyle(fontSize: 32.0)),
            ),
            Center(
              child: Text('テニス', style: TextStyle(fontSize: 32.0)),
            ),
            Center(
              child: Text('バスケ', style: TextStyle(fontSize: 32.0)),
            ),
            Center(
              child: Text('剣道', style: TextStyle(fontSize: 32.0)),
            ),
            Center(
              child: Text('柔道', style: TextStyle(fontSize: 32.0)),
            ),
            Center(
              child: Text('水泳', style: TextStyle(fontSize: 32.0)),
            ),
            Center(
              child: Text('卓球', style: TextStyle(fontSize: 32.0)),
            ),
          ],
        ),
      ),
    );
  }
}

自動でスクロールされるタブが表示されました。

Flutterタブメニュー

まとめ

Flutterでスワイプやスクロール可能なタブを実装することができました。タブの実装方法は他にもありますが、DefaultTabControllerTabBarTabBarViewを使う方法がシンプルで簡単でした。UIの中でもタブを使うケースは多いので、標準で高機能なタブのコンポーネントが備わっているのはとても助かります。

参考資料