diff --git a/examples/api/lib/cupertino/tab_scaffold/cupertino_tab_controller.0.dart b/examples/api/lib/cupertino/tab_scaffold/cupertino_tab_controller.0.dart new file mode 100644 index 00000000000..e0a5abd35be --- /dev/null +++ b/examples/api/lib/cupertino/tab_scaffold/cupertino_tab_controller.0.dart @@ -0,0 +1,72 @@ +// 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. + +// Flutter code sample for CupertinoTabController + +import 'package:flutter/cupertino.dart'; + +void main() => runApp(const TabControllerApp()); + +class TabControllerApp extends StatelessWidget { + const TabControllerApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return const CupertinoApp( + theme: CupertinoThemeData(brightness: Brightness.light), + home: TabControllerExample(), + ); + } +} + +class TabControllerExample extends StatefulWidget { + const TabControllerExample({Key? key}) : super(key: key); + + @override + State createState() => _TabControllerExampleState(); +} + +class _TabControllerExampleState extends State { + final CupertinoTabController controller = CupertinoTabController(); + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return CupertinoTabScaffold( + controller: controller, + tabBar: CupertinoTabBar( + items: const [ + BottomNavigationBarItem( + icon: Icon(CupertinoIcons.square_grid_2x2_fill), + label: 'Browse', + ), + BottomNavigationBarItem( + icon: Icon(CupertinoIcons.star_circle_fill), + label: 'Starred', + ), + ], + ), + tabBuilder: (BuildContext context, int index) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('Content of tab $index'), + const SizedBox(height: 10), + CupertinoButton( + onPressed: () => controller.index = 0, + child: const Text('Go to first tab'), + ), + ], + ) + ); + }, + ); + } +} diff --git a/examples/api/lib/cupertino/tab_scaffold/cupertino_tab_scaffold.0.dart b/examples/api/lib/cupertino/tab_scaffold/cupertino_tab_scaffold.0.dart new file mode 100644 index 00000000000..d8bf2c57fdb --- /dev/null +++ b/examples/api/lib/cupertino/tab_scaffold/cupertino_tab_scaffold.0.dart @@ -0,0 +1,85 @@ +// 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. + +// Flutter code sample for CupertinoTabScaffold + +import 'package:flutter/cupertino.dart'; + +void main() => runApp(const TabScaffoldApp()); + +class TabScaffoldApp extends StatelessWidget { + const TabScaffoldApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return const CupertinoApp( + theme: CupertinoThemeData(brightness: Brightness.light), + home: TabScaffoldExample(), + ); + } +} + +class TabScaffoldExample extends StatefulWidget { + const TabScaffoldExample({Key? key}) : super(key: key); + + @override + State createState() => _TabScaffoldExampleState(); +} + +class _TabScaffoldExampleState extends State { + @override + Widget build(BuildContext context) { + return CupertinoTabScaffold( + tabBar: CupertinoTabBar( + items: const [ + BottomNavigationBarItem( + icon: Icon(CupertinoIcons.home), + label: 'Home', + ), + BottomNavigationBarItem( + icon: Icon(CupertinoIcons.search_circle_fill), + label: 'Explore', + ), + ], + ), + tabBuilder: (BuildContext context, int index) { + return CupertinoTabView( + builder: (BuildContext context) { + return CupertinoPageScaffold( + navigationBar: CupertinoNavigationBar( + middle: Text('Page 1 of tab $index'), + ), + child: Center( + child: CupertinoButton( + child: const Text('Next page'), + onPressed: () { + Navigator.of(context).push( + CupertinoPageRoute( + builder: (BuildContext context) { + return CupertinoPageScaffold( + navigationBar: CupertinoNavigationBar( + middle: Text('Page 2 of tab $index'), + ), + child: Center( + child: CupertinoButton( + child: const Text('Back'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ), + ); + }, + ), + ); + }, + ), + ), + ); + }, + ); + }, + ); + } +} diff --git a/examples/api/test/cupertino/tab_scaffold/cupertino_tab_controller.0_test.dart b/examples/api/test/cupertino/tab_scaffold/cupertino_tab_controller.0_test.dart new file mode 100644 index 00000000000..2cca405920f --- /dev/null +++ b/examples/api/test/cupertino/tab_scaffold/cupertino_tab_controller.0_test.dart @@ -0,0 +1,24 @@ +// 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/cupertino.dart'; +import 'package:flutter_api_samples/cupertino/tab_scaffold/cupertino_tab_controller.0.dart' as example; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Can switch tabs using CupertinoTabController', (WidgetTester tester) async { + await tester.pumpWidget( + const example.TabControllerApp(), + ); + + expect(find.text('Content of tab 0'), findsOneWidget); + await tester.tap(find.byIcon(CupertinoIcons.star_circle_fill)); + await tester.pumpAndSettle(); + expect(find.text('Content of tab 1'), findsOneWidget); + + await tester.tap(find.text('Go to first tab')); + await tester.pumpAndSettle(); + expect(find.text('Content of tab 0'), findsOneWidget); + }); +} diff --git a/examples/api/test/cupertino/tab_scaffold/cupertino_tab_scaffold.0_test.dart b/examples/api/test/cupertino/tab_scaffold/cupertino_tab_scaffold.0_test.dart new file mode 100644 index 00000000000..8eb00a9f839 --- /dev/null +++ b/examples/api/test/cupertino/tab_scaffold/cupertino_tab_scaffold.0_test.dart @@ -0,0 +1,27 @@ +// 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/cupertino.dart'; +import 'package:flutter_api_samples/cupertino/tab_scaffold/cupertino_tab_scaffold.0.dart' as example; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Can use CupertinoTabView as the root widget', (WidgetTester tester) async { + await tester.pumpWidget( + const example.TabScaffoldApp(), + ); + + expect(find.text('Page 1 of tab 0'), findsOneWidget); + await tester.tap(find.byIcon(CupertinoIcons.search_circle_fill)); + await tester.pumpAndSettle(); + expect(find.text('Page 1 of tab 1'), findsOneWidget); + + await tester.tap(find.text('Next page')); + await tester.pumpAndSettle(); + expect(find.text('Page 2 of tab 1'), findsOneWidget); + await tester.tap(find.text('Back')); + await tester.pumpAndSettle(); + expect(find.text('Page 1 of tab 1'), findsOneWidget); + }); +} diff --git a/packages/flutter/lib/src/cupertino/tab_scaffold.dart b/packages/flutter/lib/src/cupertino/tab_scaffold.dart index 12191a0cf0f..3838a0410a9 100644 --- a/packages/flutter/lib/src/cupertino/tab_scaffold.dart +++ b/packages/flutter/lib/src/cupertino/tab_scaffold.dart @@ -15,47 +15,10 @@ import 'theme.dart'; /// its [CupertinoTabBar]. /// /// {@tool snippet} +/// This samples shows how [CupertinoTabController] can be used to switch tabs in +/// [CupertinoTabScaffold]. /// -/// [CupertinoTabController] can be used to switch tabs: -/// -/// ```dart -/// class MyCupertinoTabScaffoldPage extends StatefulWidget { -/// const MyCupertinoTabScaffoldPage({Key? key}) : super(key: key); -/// -/// @override -/// State createState() => _CupertinoTabScaffoldPageState(); -/// } -/// -/// class _CupertinoTabScaffoldPageState extends State { -/// final CupertinoTabController _controller = CupertinoTabController(); -/// -/// @override -/// Widget build(BuildContext context) { -/// return CupertinoTabScaffold( -/// tabBar: CupertinoTabBar( -/// items: const [ -/// // ... -/// ], -/// ), -/// controller: _controller, -/// tabBuilder: (BuildContext context, int index) { -/// return Center( -/// child: CupertinoButton( -/// child: const Text('Go to first tab'), -/// onPressed: () => _controller.index = 0, -/// ) -/// ); -/// } -/// ); -/// } -/// -/// @override -/// void dispose() { -/// _controller.dispose(); -/// super.dispose(); -/// } -/// } -/// ``` +/// ** See code in examples/api/lib/cupertino/tab_scaffold/cupertino_tab_controller.0.dart ** /// {@end-tool} /// /// See also: @@ -138,54 +101,10 @@ class CupertinoTabController extends ChangeNotifier { /// (via [State.setState], for instance) from its descendant rather than from /// its ancestor. /// -/// {@tool snippet} -/// +/// {@tool dartpad} /// A sample code implementing a typical iOS information architecture with tabs. /// -/// ```dart -/// CupertinoTabScaffold( -/// tabBar: CupertinoTabBar( -/// items: const [ -/// // ... -/// ], -/// ), -/// tabBuilder: (BuildContext context, int index) { -/// return CupertinoTabView( -/// builder: (BuildContext context) { -/// return CupertinoPageScaffold( -/// navigationBar: CupertinoNavigationBar( -/// middle: Text('Page 1 of tab $index'), -/// ), -/// child: Center( -/// child: CupertinoButton( -/// child: const Text('Next page'), -/// onPressed: () { -/// Navigator.of(context).push( -/// CupertinoPageRoute( -/// builder: (BuildContext context) { -/// return CupertinoPageScaffold( -/// navigationBar: CupertinoNavigationBar( -/// middle: Text('Page 2 of tab $index'), -/// ), -/// child: Center( -/// child: CupertinoButton( -/// child: const Text('Back'), -/// onPressed: () { Navigator.of(context).pop(); }, -/// ), -/// ), -/// ); -/// }, -/// ), -/// ); -/// }, -/// ), -/// ), -/// ); -/// }, -/// ); -/// }, -/// ) -/// ``` +/// ** See code in examples/api/lib/cupertino/tab_scaffold/cupertino_tab_scaffold.0.dart ** /// {@end-tool} /// /// To push a route above all tabs instead of inside the currently selected one