1// Copyright 2017 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5import 'package:flutter/material.dart'; 6 7class AppBarBottomSample extends StatefulWidget { 8 @override 9 _AppBarBottomSampleState createState() => _AppBarBottomSampleState(); 10} 11 12class _AppBarBottomSampleState extends State<AppBarBottomSample> with SingleTickerProviderStateMixin { 13 TabController _tabController; 14 15 @override 16 void initState() { 17 super.initState(); 18 _tabController = TabController(vsync: this, length: choices.length); 19 } 20 21 @override 22 void dispose() { 23 _tabController.dispose(); 24 super.dispose(); 25 } 26 27 void _nextPage(int delta) { 28 final int newIndex = _tabController.index + delta; 29 if (newIndex < 0 || newIndex >= _tabController.length) 30 return; 31 _tabController.animateTo(newIndex); 32 } 33 34 @override 35 Widget build(BuildContext context) { 36 return MaterialApp( 37 home: Scaffold( 38 appBar: AppBar( 39 title: const Text('AppBar Bottom Widget'), 40 leading: IconButton( 41 tooltip: 'Previous choice', 42 icon: const Icon(Icons.arrow_back), 43 onPressed: () { _nextPage(-1); }, 44 ), 45 actions: <Widget>[ 46 IconButton( 47 icon: const Icon(Icons.arrow_forward), 48 tooltip: 'Next choice', 49 onPressed: () { _nextPage(1); }, 50 ), 51 ], 52 bottom: PreferredSize( 53 preferredSize: const Size.fromHeight(48.0), 54 child: Theme( 55 data: Theme.of(context).copyWith(accentColor: Colors.white), 56 child: Container( 57 height: 48.0, 58 alignment: Alignment.center, 59 child: TabPageSelector(controller: _tabController), 60 ), 61 ), 62 ), 63 ), 64 body: TabBarView( 65 controller: _tabController, 66 children: choices.map<Widget>((Choice choice) { 67 return Padding( 68 padding: const EdgeInsets.all(16.0), 69 child: ChoiceCard(choice: choice), 70 ); 71 }).toList(), 72 ), 73 ), 74 ); 75 } 76} 77 78class Choice { 79 const Choice({ this.title, this.icon }); 80 final String title; 81 final IconData icon; 82} 83 84const List<Choice> choices = <Choice>[ 85 Choice(title: 'CAR', icon: Icons.directions_car), 86 Choice(title: 'BICYCLE', icon: Icons.directions_bike), 87 Choice(title: 'BOAT', icon: Icons.directions_boat), 88 Choice(title: 'BUS', icon: Icons.directions_bus), 89 Choice(title: 'TRAIN', icon: Icons.directions_railway), 90 Choice(title: 'WALK', icon: Icons.directions_walk), 91]; 92 93class ChoiceCard extends StatelessWidget { 94 const ChoiceCard({ Key key, this.choice }) : super(key: key); 95 96 final Choice choice; 97 98 @override 99 Widget build(BuildContext context) { 100 final TextStyle textStyle = Theme.of(context).textTheme.display1; 101 return Card( 102 color: Colors.white, 103 child: Center( 104 child: Column( 105 mainAxisSize: MainAxisSize.min, 106 crossAxisAlignment: CrossAxisAlignment.center, 107 children: <Widget>[ 108 Icon(choice.icon, size: 128.0, color: textStyle.color), 109 Text(choice.title, style: textStyle), 110 ], 111 ), 112 ), 113 ); 114 } 115} 116 117void main() { 118 runApp(AppBarBottomSample()); 119} 120 121/* 122Sample Catalog 123 124Title: AppBar with a custom bottom widget. 125 126Summary: An AppBar that includes a bottom widget. Any widget 127with a PreferredSize can appear at the bottom of an AppBar. 128 129Summary: Any widget with a PreferredSize can appear at the bottom of an AppBar. 130 131Description: 132Typically an AppBar's bottom widget is a TabBar however any widget with a 133PreferredSize can be used. In this app, the app bar's bottom widget is a 134TabPageSelector that displays the relative position of the selected page 135in the app's TabBarView. The arrow buttons in the toolbar part of the app 136bar and they select the previous or the next page. 137 138Classes: AppBar, PreferredSize, TabBarView, TabController 139 140Sample: AppBarBottomSample 141 142See also: 143 - The "Components-Tabs" section of the material design specification: 144 <https://material.io/go/design-tabs> 145*/ 146