// Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'package:flutter/material.dart'; /// Flutter code sample for [TabController]. void main() => runApp(const TabControllerExampleApp()); class TabControllerExampleApp extends StatelessWidget { const TabControllerExampleApp({super.key}); static const List tabs = [ Tab(text: 'Zeroth'), Tab(text: 'First'), Tab(text: 'Second'), ]; @override Widget build(BuildContext context) { return const MaterialApp( home: TabControllerExample(tabs: tabs), ); } } class TabControllerExample extends StatelessWidget { const TabControllerExample({ required this.tabs, super.key, }); final List tabs; @override Widget build(BuildContext context) { return DefaultTabController( length: tabs.length, child: DefaultTabControllerListener( onTabChanged: (int index) { debugPrint('tab changed: $index'); }, child: Scaffold( appBar: AppBar( bottom: TabBar(tabs: tabs), ), body: TabBarView( children: tabs.map((Tab tab) { return Center( child: Text( '${tab.text!} Tab', style: Theme.of(context).textTheme.headlineSmall, ), ); }).toList(), ), ), ), ); } } class DefaultTabControllerListener extends StatefulWidget { const DefaultTabControllerListener({ required this.onTabChanged, required this.child, super.key, }); final ValueChanged onTabChanged; final Widget child; @override State createState() => _DefaultTabControllerListenerState(); } class _DefaultTabControllerListenerState extends State { TabController? _controller; @override void didChangeDependencies() { super.didChangeDependencies(); final TabController? defaultTabController = DefaultTabController.maybeOf(context); assert(() { if (defaultTabController == null) { throw FlutterError( 'No DefaultTabController for ${widget.runtimeType}.\n' 'When creating a ${widget.runtimeType}, you must ensure that there ' 'is a DefaultTabController above the ${widget.runtimeType}.', ); } return true; }()); if (defaultTabController != _controller) { _controller?.removeListener(_listener); _controller = defaultTabController; _controller?.addListener(_listener); } } void _listener() { final TabController? controller = _controller; if (controller == null || controller.indexIsChanging) { return; } widget.onTabChanged(controller.index); } @override void dispose() { _controller?.removeListener(_listener); super.dispose(); } @override Widget build(BuildContext context) { return widget.child; } }