LoginSignup
1

More than 1 year has passed since last update.

posted at

flutter_blocを使ってみる その6 - BLoCでTabViewを作成する

BLoCでTabViewを作成する方法

FlutterでTabViewを作るときはDefaultTabControllerを使うことが多いですが、BLoCを使うこともできます。

flutter_blocを用いる場合、以下のように作ります。

  • Tab情報をenum等のStateとしてして持つ。
  • Tabが選択された際にEventをBLoCに送る。EventはTab情報(State)をプロパティとして持つ。
  • Eventを受け取ったBlocが選択されたTabをStateとして通知する。
  • View側がStateを受け取り、選ばれたTabの内容を描画する。

実際のコード

flutter_blocを使って以下のようなコードを作成します。

BLoC

// Bloc
// BlocState
enum AppTab { a, b }

// BlocEvent
abstract class TabEvent extends Equatable {
  const TabEvent();
}

class UpdateTab extends TabEvent {
  final AppTab tab;

  const UpdateTab(this.tab);

  @override
  List<Object> get props => [tab];

  @override
  String toString() => 'UpdateTab { tab: $tab }';
}

// Bloc
class TabBloc extends Bloc<TabEvent, AppTab> {
  TabBloc() : super(AppTab.a);

  @override
  Stream<AppTab> mapEventToState(TabEvent event) async* {
    if (event is UpdateTab) {
      yield event.tab;
    }
  }
}

View

void main() {
  runApp(MyApp());
}


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider<TabBloc>(
        create: (context) => TabBloc(),
        child: TabBlocPage(),
      ),
    );
  }
}

class TabBlocPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<TabBloc, AppTab>(
      builder: (context, activeTab) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('TabBlocExample'),
          ),
          // 選ばれたTab(State)によって描画する
          body: activeTab == AppTab.a ? TabA() : TabB(),
          bottomNavigationBar: TabSelector(
            activeTab: activeTab,
            // ユーザーが選んだTabをEventに持たせて送るFunctionをTabSelectorのメソッドに割り当てる
            onTabSelected: (tab) => BlocProvider.of<TabBloc>(context).add(UpdateTab(tab)),
          ),
        );
      },
    );
  }
}

// TabView
class TabA extends StatelessWidget {
  const TabA({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(child: Text('TabA')),
    );
  }
}

class TabB extends StatelessWidget {
  const TabB({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(child: Text('TabB')),
    );
  }
}

// BottomNavigationBar
class TabSelector extends StatelessWidget {
  const TabSelector({
    Key key,
    this.activeTab,
    this.onTabSelected,
  }) : super(key: key);
  final AppTab activeTab;
  final Function(AppTab) onTabSelected;

  @override
  Widget build(BuildContext context) {
    return BottomNavigationBar(
      items: [
        BottomNavigationBarItem(
          icon: Icon(Icons.circle),
          label: 'TabA',
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.crop_square),
          label: 'TabB',
        ),
      ],
      currentIndex: AppTab.values.indexOf(activeTab),
      selectedItemColor: Colors.amber[800],
      // ユーザーがTabを選択した際にBLoCにEventを送る
      onTap: (index) => onTabSelected(AppTab.values[index]),
    );
  }
}

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1