CupertinoTabBar (#10264)
Move some Cupertino colors to a common file. Create a CupertinoTabBar widget to mimic iOS looks
This commit is contained in:
parent
f53d0fece2
commit
69c2542458
@ -8,7 +8,9 @@
|
||||
library cupertino;
|
||||
|
||||
export 'src/cupertino/activity_indicator.dart';
|
||||
export 'src/cupertino/bottom_tab_bar.dart';
|
||||
export 'src/cupertino/button.dart';
|
||||
export 'src/cupertino/colors.dart';
|
||||
export 'src/cupertino/dialog.dart';
|
||||
export 'src/cupertino/page.dart';
|
||||
export 'src/cupertino/slider.dart';
|
||||
|
@ -6,6 +6,8 @@ import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'colors.dart';
|
||||
|
||||
/// An iOS-style activity indicator.
|
||||
///
|
||||
/// See also:
|
||||
@ -80,7 +82,7 @@ class _CupertinoActivityIndicatorState extends State<CupertinoActivityIndicator>
|
||||
const double _kTwoPI = math.PI * 2.0;
|
||||
const int _kTickCount = 12;
|
||||
const int _kHalfTickCount = _kTickCount ~/ 2;
|
||||
const Color _kTickColor = const Color(0xFFE0E0E0);
|
||||
const Color _kTickColor = CupertinoColors.lightBackgroundGray;
|
||||
const Color _kActiveTickColor = const Color(0xFF9D9D9D);
|
||||
final RRect _kTickFundamentalRRect = new RRect.fromLTRBXY(-10.0, 1.0, -5.0, -1.0, 1.0, 1.0);
|
||||
|
||||
|
161
packages/flutter/lib/src/cupertino/bottom_tab_bar.dart
Normal file
161
packages/flutter/lib/src/cupertino/bottom_tab_bar.dart
Normal file
@ -0,0 +1,161 @@
|
||||
// Copyright 2017 The Chromium 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 'dart:ui' show ImageFilter;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'colors.dart';
|
||||
|
||||
// Standard iOS 10 tab bar height.
|
||||
const double _kTabBarHeight = 50.0;
|
||||
|
||||
const Color _kDefaultTabBarBackgroundColor = const Color(0xCCF8F8F8);
|
||||
|
||||
class CupertinoTabBar extends StatelessWidget {
|
||||
CupertinoTabBar({
|
||||
Key key,
|
||||
@required this.items,
|
||||
this.onTap,
|
||||
this.currentIndex: 0,
|
||||
this.backgroundColor: _kDefaultTabBarBackgroundColor,
|
||||
this.activeColor: CupertinoColors.activeBlue,
|
||||
this.inactiveColor: CupertinoColors.inactiveGray,
|
||||
this.iconSize: 24.0,
|
||||
}) : super(key: key) {
|
||||
assert(items != null);
|
||||
assert(items.length >= 2);
|
||||
assert(0 <= currentIndex && currentIndex < items.length);
|
||||
assert(iconSize != null);
|
||||
}
|
||||
|
||||
/// The interactive items laid out within the bottom navigation bar.
|
||||
final List<BottomNavigationBarItem> items;
|
||||
|
||||
/// The callback that is called when a item is tapped.
|
||||
///
|
||||
/// The widget creating the bottom navigation bar needs to keep track of the
|
||||
/// current index and call `setState` to rebuild it with the newly provided
|
||||
/// index.
|
||||
final ValueChanged<int> onTap;
|
||||
|
||||
/// The index into [items] of the current active item.
|
||||
final int currentIndex;
|
||||
|
||||
/// The background color of the tab bar. If it contains transparency, the
|
||||
/// tab bar will automatically produce a blurring effect to the content
|
||||
/// behind it.
|
||||
final Color backgroundColor;
|
||||
|
||||
/// The foreground color of the icon and title for the [BottomNavigationBarItem]
|
||||
/// of the selected tab.
|
||||
final Color activeColor;
|
||||
|
||||
/// The foreground color of the icon and title for the [BottomNavigationBarItem]s
|
||||
/// in the unselected state.
|
||||
final Color inactiveColor;
|
||||
|
||||
/// The size of all of the [BottomNavigationBarItem] icons.
|
||||
///
|
||||
/// This value is used to to configure the [IconTheme] for the navigation
|
||||
/// bar. When a [BottomNavigationBarItem.icon] widget is not an [Icon] the widget
|
||||
/// should configure itself to match the icon theme's size and color.
|
||||
final double iconSize;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bool addBlur = backgroundColor.alpha != 0xFF;
|
||||
|
||||
Widget result = new DecoratedBox(
|
||||
decoration: new BoxDecoration(
|
||||
border: const Border(
|
||||
top: const BorderSide(
|
||||
color: const Color(0x4C000000),
|
||||
width: 0.0, // One physical pixel.
|
||||
style: BorderStyle.solid,
|
||||
),
|
||||
),
|
||||
color: backgroundColor,
|
||||
),
|
||||
// TODO(xster): allow icons-only versions of the tab bar too.
|
||||
child: new SizedBox(
|
||||
height: _kTabBarHeight,
|
||||
child: IconTheme.merge( // Default with the inactive state.
|
||||
data: new IconThemeData(
|
||||
color: inactiveColor,
|
||||
size: iconSize,
|
||||
),
|
||||
child: DefaultTextStyle.merge( // Default with the inactive state.
|
||||
style: new TextStyle(
|
||||
fontSize: 10.0,
|
||||
letterSpacing: 0.12,
|
||||
color: inactiveColor,
|
||||
),
|
||||
child: new Row(
|
||||
// Align bottom since we want the labels to be aligned.
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: _buildTabItems(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (addBlur) {
|
||||
// For non-opaque backgrounds, apply a blur effect.
|
||||
result = new ClipRect(
|
||||
child: new BackdropFilter(
|
||||
filter: new ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
|
||||
child: result,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
List<Widget> _buildTabItems() {
|
||||
final List<Widget> result = <Widget>[];
|
||||
|
||||
for (int index = 0; index < items.length; ++index) {
|
||||
result.add(
|
||||
_wrapActiveItem(
|
||||
new Expanded(
|
||||
child: new GestureDetector(
|
||||
onTap: onTap == null ? null : () { onTap(index); },
|
||||
child: new Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: new Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: <Widget> [
|
||||
new Expanded(child: new Center(child: items[index].icon)),
|
||||
items[index].title,
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
active: index == currentIndex,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Change the active tab item's icon and title colors to active.
|
||||
Widget _wrapActiveItem(Widget item, { bool active }) {
|
||||
if (!active)
|
||||
return item;
|
||||
|
||||
return IconTheme.merge(
|
||||
data: new IconThemeData(color: activeColor),
|
||||
child: DefaultTextStyle.merge(
|
||||
style: new TextStyle(color: activeColor),
|
||||
child: item,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -5,9 +5,8 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
// TODO(xster): move this to a common Cupertino color palette with the next yak.
|
||||
const Color _kBlue = const Color(0xFF007AFF);
|
||||
const Color _kWhite = const Color(0xFFFFFFFF);
|
||||
import 'colors.dart';
|
||||
|
||||
const Color _kDisabledBackground = const Color(0xFFA9A9A9);
|
||||
const Color _kDisabledForeground = const Color(0xFFC4C4C4);
|
||||
|
||||
@ -16,7 +15,7 @@ const TextStyle _kButtonTextStyle = const TextStyle(
|
||||
inherit: false,
|
||||
fontSize: 15.0,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: _kBlue,
|
||||
color: CupertinoColors.activeBlue,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
);
|
||||
|
||||
@ -25,7 +24,7 @@ final TextStyle _kDisabledButtonTextStyle = _kButtonTextStyle.copyWith(
|
||||
);
|
||||
|
||||
final TextStyle _kBackgroundButtonTextStyle = _kButtonTextStyle.copyWith(
|
||||
color: _kWhite,
|
||||
color: CupertinoColors.white,
|
||||
);
|
||||
|
||||
const EdgeInsets _kButtonPadding = const EdgeInsets.all(16.0);
|
||||
|
40
packages/flutter/lib/src/cupertino/colors.dart
Normal file
40
packages/flutter/lib/src/cupertino/colors.dart
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2017 The Chromium 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 'dart:ui' show Color;
|
||||
|
||||
class CupertinoColors {
|
||||
CupertinoColors._();
|
||||
|
||||
/// iOS 10's default blue color. Used to indicate active elements such as
|
||||
/// buttons, selected tabs and your own chat bubbles.
|
||||
static const Color activeBlue = const Color(0xFF007AFF);
|
||||
|
||||
/// iOS 10's default green color. Used to indicate active accents such as
|
||||
/// the switch in its on state and some accent buttons such as the call button
|
||||
/// and Apple Map's 'Go' button.
|
||||
static const Color activeGreen = const Color(0xFF4CD964);
|
||||
|
||||
/// Opaque white color. Used for backgrounds and fonts against dark backgrounds.
|
||||
static const Color white = const Color(0xFFFFFFFF);
|
||||
|
||||
/// Opaque black color. Used for texts against light backgrounds.
|
||||
static const Color black = const Color(0xFF000000);
|
||||
|
||||
/// Used in iOS 10 for light background fills such as the chat bubble background.
|
||||
static const Color lightBackgroundGray = const Color(0xFFE5E5EA);
|
||||
|
||||
/// Used in iOS 10 for unselected selectables such as tab bar items in their
|
||||
/// inactive state.
|
||||
///
|
||||
/// Not the same gray as disabled buttons etc.
|
||||
static const Color inactiveGray = const Color(0xFF929292);
|
||||
|
||||
/// Used for iOS 10 for destructive actions such as the delete actions in
|
||||
/// table view cells and dialogs.
|
||||
///
|
||||
/// Not the same red as the camera shutter or springboard icon notifications
|
||||
/// or the foreground red theme in various native apps such as HealthKit.
|
||||
static const Color destructiveRed = const Color(0xFFFF3B30);
|
||||
}
|
@ -6,6 +6,8 @@ import 'dart:ui' show ImageFilter;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'colors.dart';
|
||||
|
||||
// TODO(abarth): These constants probably belong somewhere more general.
|
||||
|
||||
const TextStyle _kCupertinoDialogTitleStyle = const TextStyle(
|
||||
@ -13,7 +15,7 @@ const TextStyle _kCupertinoDialogTitleStyle = const TextStyle(
|
||||
inherit: false,
|
||||
fontSize: 17.5,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: const Color(0xFF000000),
|
||||
color: CupertinoColors.black,
|
||||
height: 1.25,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
);
|
||||
@ -23,7 +25,7 @@ const TextStyle _kCupertinoDialogContentStyle = const TextStyle(
|
||||
inherit: false,
|
||||
fontSize: 12.4,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: const Color(0xFF000000),
|
||||
color: CupertinoColors.black,
|
||||
height: 1.35,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
);
|
||||
@ -33,7 +35,7 @@ const TextStyle _kCupertinoDialogActionStyle = const TextStyle(
|
||||
inherit: false,
|
||||
fontSize: 16.8,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: const Color(0xFF027AFF),
|
||||
color: CupertinoColors.activeBlue,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
);
|
||||
|
||||
@ -180,7 +182,6 @@ class CupertinoAlertDialog extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
const Color _kDestructiveActionColor = const Color(0xFFFF3B30);
|
||||
|
||||
/// A button typically used in a [CupertinoAlertDialog].
|
||||
///
|
||||
@ -228,7 +229,7 @@ class CupertinoDialogAction extends StatelessWidget {
|
||||
style = style.copyWith(fontWeight: FontWeight.w600);
|
||||
|
||||
if (isDestructiveAction)
|
||||
style = style.copyWith(color: _kDestructiveActionColor);
|
||||
style = style.copyWith(color: CupertinoColors.destructiveRed);
|
||||
|
||||
if (!enabled)
|
||||
style = style.copyWith(color: style.color.withOpacity(0.5));
|
||||
|
@ -10,6 +10,7 @@ import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'colors.dart';
|
||||
import 'thumb_painter.dart';
|
||||
|
||||
/// An iOS-style slider.
|
||||
@ -48,7 +49,7 @@ class CupertinoSlider extends StatefulWidget {
|
||||
this.min: 0.0,
|
||||
this.max: 1.0,
|
||||
this.divisions,
|
||||
this.activeColor: const Color(0xFF027AFF),
|
||||
this.activeColor: CupertinoColors.activeBlue,
|
||||
}) : assert(value != null),
|
||||
assert(min != null),
|
||||
assert(max != null),
|
||||
|
@ -10,6 +10,7 @@ import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'colors.dart';
|
||||
import 'thumb_painter.dart';
|
||||
|
||||
/// An iOS-style switch.
|
||||
@ -30,7 +31,7 @@ class CupertinoSwitch extends StatefulWidget {
|
||||
Key key,
|
||||
@required this.value,
|
||||
@required this.onChanged,
|
||||
this.activeColor: const Color(0xFF4CD964),
|
||||
this.activeColor: CupertinoColors.activeGreen,
|
||||
}) : super(key: key);
|
||||
|
||||
/// Whether this switch is on or off.
|
||||
@ -130,7 +131,7 @@ const double _kTrackInnerLength = _kTrackInnerEnd - _kTrackInnerStart;
|
||||
const double _kSwitchWidth = 59.0;
|
||||
const double _kSwitchHeight = 39.0;
|
||||
|
||||
const Color _kTrackColor = const Color(0xFFE5E5E5);
|
||||
const Color _kTrackColor = CupertinoColors.lightBackgroundGray;
|
||||
const Duration _kReactionDuration = const Duration(milliseconds: 300);
|
||||
const Duration _kToggleDuration = const Duration(milliseconds: 200);
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
import 'package:flutter/painting.dart';
|
||||
|
||||
import 'colors.dart';
|
||||
|
||||
final MaskFilter _kShadowMaskFilter = new MaskFilter.blur(BlurStyle.normal, BoxShadow.convertRadiusToSigma(1.0));
|
||||
|
||||
/// Paints an iOS-style slider thumb.
|
||||
@ -12,7 +14,7 @@ final MaskFilter _kShadowMaskFilter = new MaskFilter.blur(BlurStyle.normal, BoxS
|
||||
class CupertinoThumbPainter {
|
||||
/// Creates an object that paints an iOS-style slider thumb.
|
||||
CupertinoThumbPainter({
|
||||
this.color: const Color(0xFFFFFFFF),
|
||||
this.color: CupertinoColors.white,
|
||||
this.shadowColor: const Color(0x2C000000),
|
||||
});
|
||||
|
||||
|
@ -35,44 +35,6 @@ enum BottomNavigationBarType {
|
||||
shifting,
|
||||
}
|
||||
|
||||
/// An interactive destination label within [BottomNavigationBar] with an icon
|
||||
/// and title.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [BottomNavigationBar]
|
||||
/// * <https://material.google.com/components/bottom-navigation.html>
|
||||
class BottomNavigationBarItem {
|
||||
/// Creates an item that is used with [BottomNavigationBar.items].
|
||||
///
|
||||
/// The arguments [icon] and [title] should not be null.
|
||||
BottomNavigationBarItem({
|
||||
@required this.icon,
|
||||
@required this.title,
|
||||
this.backgroundColor
|
||||
}) {
|
||||
assert(icon != null);
|
||||
assert(title != null);
|
||||
}
|
||||
|
||||
/// The icon of the item.
|
||||
///
|
||||
/// Typically the icon is an [Icon] or an [ImageIcon] widget. If another type
|
||||
/// of widget is provided then it should configure itself to match the current
|
||||
/// [IconTheme] size and color.
|
||||
final Widget icon;
|
||||
|
||||
/// The title of the item.
|
||||
final Widget title;
|
||||
|
||||
/// The color of the background radial animation.
|
||||
///
|
||||
/// If the navigation bar's type is [BottomNavigationBarType.shifting], then
|
||||
/// the entire bar is flooded with the [backgroundColor] when this item is
|
||||
/// tapped.
|
||||
final Color backgroundColor;
|
||||
}
|
||||
|
||||
/// A material widget displayed at the bottom of an app for selecting among a
|
||||
/// small number of views.
|
||||
///
|
||||
|
@ -0,0 +1,58 @@
|
||||
// Copyright 2017 The Chromium 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 'dart:ui' show Color;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'framework.dart';
|
||||
|
||||
/// An interactive button within either material's [BottomNavigationBar]
|
||||
/// or the iOS themed [CupertinoTabBar] with an icon and title.
|
||||
///
|
||||
/// This calss is rarely used in isolation. Commonly embedded in one of the
|
||||
/// bottom navigation widgets above.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [BottomNavigationBar]
|
||||
/// * <https://material.google.com/components/bottom-navigation.html>
|
||||
/// * [CupertinoTabBar]
|
||||
/// * <https://developer.apple.com/ios/human-interface-guidelines/ui-bars/tab-bars>
|
||||
class BottomNavigationBarItem {
|
||||
/// Creates an item that is used with [BottomNavigationBar.items].
|
||||
///
|
||||
/// The arguments [icon] and [title] should not be null.
|
||||
const BottomNavigationBarItem({
|
||||
@required this.icon,
|
||||
@required this.title,
|
||||
this.backgroundColor,
|
||||
}) : assert(icon != null),
|
||||
assert(title != null);
|
||||
|
||||
/// The icon of the item.
|
||||
///
|
||||
/// Typically the icon is an [Icon] or an [ImageIcon] widget. If another type
|
||||
/// of widget is provided then it should configure itself to match the current
|
||||
/// [IconTheme] size and color.
|
||||
final Widget icon;
|
||||
|
||||
/// The title of the item.
|
||||
final Widget title;
|
||||
|
||||
/// The color of the background radial animation for material [BottomNavigationBar].
|
||||
///
|
||||
/// If the navigation bar's type is [BottomNavigationBarType.shifting], then
|
||||
/// the entire bar is flooded with the [backgroundColor] when this item is
|
||||
/// tapped.
|
||||
///
|
||||
/// Not used for [CupertinoTabBar]. Control the invariant bar color directly
|
||||
/// via [CupertinoTabBar.backgroundColor].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Icon.color] and [ImageIcon.color] to control the foreground color of
|
||||
/// the icons themselves.
|
||||
final Color backgroundColor;
|
||||
}
|
@ -22,6 +22,7 @@ export 'src/widgets/async.dart';
|
||||
export 'src/widgets/banner.dart';
|
||||
export 'src/widgets/basic.dart';
|
||||
export 'src/widgets/binding.dart';
|
||||
export 'src/widgets/bottom_navigation_bar_item.dart';
|
||||
export 'src/widgets/container.dart';
|
||||
export 'src/widgets/debug.dart';
|
||||
export 'src/widgets/dismissible.dart';
|
||||
|
112
packages/flutter/test/cupertino/bottom_tab_bar_test.dart
Normal file
112
packages/flutter/test/cupertino/bottom_tab_bar_test.dart
Normal file
@ -0,0 +1,112 @@
|
||||
// Copyright 2017 The Chromium 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/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../services/mocks_for_image_cache.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Need at least 2 tabs', (WidgetTester tester) async {
|
||||
try {
|
||||
await tester.pumpWidget(new CupertinoTabBar(
|
||||
items: <BottomNavigationBarItem>[
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 1'),
|
||||
),
|
||||
],
|
||||
));
|
||||
fail('Should not be possible to create a tab bar with just one item');
|
||||
} on AssertionError {
|
||||
// Exception expected.
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('Active and inactive colors', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(new CupertinoTabBar(
|
||||
items: <BottomNavigationBarItem>[
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 1'),
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 2'),
|
||||
),
|
||||
],
|
||||
currentIndex: 1,
|
||||
activeColor: const Color(0xFF123456),
|
||||
inactiveColor: const Color(0xFF654321),
|
||||
));
|
||||
|
||||
final RichText actualInactive = tester.widget(find.descendant(
|
||||
of: find.text('Tab 1'),
|
||||
matching: find.byType(RichText),
|
||||
));
|
||||
expect(actualInactive.text.style.color, const Color(0xFF654321));
|
||||
|
||||
final RichText actualActive = tester.widget(find.descendant(
|
||||
of: find.text('Tab 2'),
|
||||
matching: find.byType(RichText),
|
||||
));
|
||||
expect(actualActive.text.style.color, const Color(0xFF123456));
|
||||
});
|
||||
|
||||
testWidgets('Opaque background does not add blur effects', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(new CupertinoTabBar(
|
||||
items: <BottomNavigationBarItem>[
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 1'),
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 2'),
|
||||
),
|
||||
],
|
||||
));
|
||||
|
||||
expect(find.byType(BackdropFilter), findsOneWidget);
|
||||
|
||||
await tester.pumpWidget(new CupertinoTabBar(
|
||||
items: <BottomNavigationBarItem>[
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 1'),
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 2'),
|
||||
),
|
||||
],
|
||||
backgroundColor: const Color(0xFFFFFFFF), // Opaque white.
|
||||
));
|
||||
|
||||
expect(find.byType(BackdropFilter), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('Tap callback', (WidgetTester tester) async {
|
||||
int callbackTab;
|
||||
|
||||
await tester.pumpWidget(new CupertinoTabBar(
|
||||
items: <BottomNavigationBarItem>[
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 1'),
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 2'),
|
||||
),
|
||||
],
|
||||
currentIndex: 1,
|
||||
onTap: (int tab) { callbackTab = tab; },
|
||||
));
|
||||
|
||||
await tester.tap(find.text('Tab 1'));
|
||||
expect(callbackTab, 0);
|
||||
});
|
||||
}
|
@ -14,11 +14,11 @@ void main() {
|
||||
home: new Scaffold(
|
||||
bottomNavigationBar: new BottomNavigationBar(
|
||||
items: <BottomNavigationBarItem>[
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.ac_unit),
|
||||
title: const Text('AC')
|
||||
),
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.access_alarm),
|
||||
title: const Text('Alarm')
|
||||
)
|
||||
@ -42,11 +42,11 @@ void main() {
|
||||
home: new Scaffold(
|
||||
bottomNavigationBar: new BottomNavigationBar(
|
||||
items: <BottomNavigationBarItem>[
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.ac_unit),
|
||||
title: const Text('AC')
|
||||
),
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.access_alarm),
|
||||
title: const Text('Alarm')
|
||||
)
|
||||
@ -69,11 +69,11 @@ void main() {
|
||||
bottomNavigationBar: new BottomNavigationBar(
|
||||
type: BottomNavigationBarType.shifting,
|
||||
items: <BottomNavigationBarItem>[
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.ac_unit),
|
||||
title: const Text('AC')
|
||||
),
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.access_alarm),
|
||||
title: const Text('Alarm')
|
||||
)
|
||||
@ -95,11 +95,11 @@ void main() {
|
||||
currentIndex: 1,
|
||||
type: BottomNavigationBarType.shifting,
|
||||
items: <BottomNavigationBarItem>[
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.ac_unit),
|
||||
title: const Text('AC')
|
||||
),
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.access_alarm),
|
||||
title: const Text('Alarm')
|
||||
)
|
||||
@ -124,19 +124,19 @@ void main() {
|
||||
bottomNavigationBar: new BottomNavigationBar(
|
||||
type: BottomNavigationBarType.shifting,
|
||||
items: <BottomNavigationBarItem>[
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.ac_unit),
|
||||
title: const Text('AC')
|
||||
),
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.access_alarm),
|
||||
title: const Text('Alarm')
|
||||
),
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.access_time),
|
||||
title: const Text('Time')
|
||||
),
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.add),
|
||||
title: const Text('Add')
|
||||
)
|
||||
@ -185,19 +185,19 @@ void main() {
|
||||
bottomNavigationBar: new BottomNavigationBar(
|
||||
type: BottomNavigationBarType.shifting,
|
||||
items: <BottomNavigationBarItem>[
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.ac_unit),
|
||||
title: const Text('AC')
|
||||
),
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.access_alarm),
|
||||
title: const Text('Alarm')
|
||||
),
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.access_time),
|
||||
title: const Text('Time')
|
||||
),
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.add),
|
||||
title: const Text('Add')
|
||||
)
|
||||
@ -223,19 +223,19 @@ void main() {
|
||||
bottomNavigationBar: new BottomNavigationBar(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
items: <BottomNavigationBarItem>[
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.ac_unit),
|
||||
title: const Text('AC')
|
||||
),
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.access_alarm),
|
||||
title: const Text('Alarm')
|
||||
),
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.access_time),
|
||||
title: const Text('Time')
|
||||
),
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.add),
|
||||
title: const Text('Add')
|
||||
)
|
||||
@ -259,7 +259,7 @@ void main() {
|
||||
bottomNavigationBar: new BottomNavigationBar(
|
||||
iconSize: 12.0,
|
||||
items: <BottomNavigationBarItem>[
|
||||
new BottomNavigationBarItem(
|
||||
const BottomNavigationBarItem(
|
||||
title: const Text('A'),
|
||||
icon: const Icon(Icons.ac_unit),
|
||||
),
|
||||
|
Loading…
x
Reference in New Issue
Block a user