Commit fcf67408 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Factor BackButton out of AppBar (#8491)

This widget is useful on its own. This patch factors it out of AppBar so
folks can use it separately.

Fixes #8489
parent 17057bb4
......@@ -15,6 +15,7 @@ export 'src/material/about.dart';
export 'src/material/app.dart';
export 'src/material/app_bar.dart';
export 'src/material/arc.dart';
export 'src/material/back_button.dart';
export 'src/material/bottom_navigation_bar.dart';
export 'src/material/bottom_sheet.dart';
export 'src/material/button.dart';
......
......@@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'back_button.dart';
import 'constants.dart';
import 'flexible_space_bar.dart';
import 'icon.dart';
......@@ -188,7 +189,7 @@ class AppBar extends StatefulWidget {
/// example, if the [AppBar] is in a [Scaffold] that also has a [Drawer], the
/// [Scaffold] will fill this widget with an [IconButton] that opens the
/// drawer. If there's no [Drawer] and the parent [Navigator] can go back, the
/// [AppBar] will use an [IconButton] that calls [Navigator.pop].
/// [AppBar] will use a [BackButton] that calls [Navigator.maybePop].
final Widget leading;
/// The primary widget displayed in the appbar.
......@@ -345,10 +346,6 @@ class _AppBarState extends State<AppBar> {
Scaffold.of(context).openDrawer();
}
void _handleBackButton() {
Navigator.of(context).maybePop();
}
@override
Widget build(BuildContext context) {
final ThemeData themeData = Theme.of(context);
......@@ -383,24 +380,8 @@ class _AppBarState extends State<AppBar> {
tooltip: 'Open navigation menu' // TODO(ianh): Figure out how to localize this string
);
} else {
if (_canPop) {
IconData backIcon;
switch (Theme.of(context).platform) {
case TargetPlatform.android:
case TargetPlatform.fuchsia:
backIcon = Icons.arrow_back;
break;
case TargetPlatform.iOS:
backIcon = Icons.arrow_back_ios;
break;
}
assert(backIcon != null);
leading = new IconButton(
icon: new Icon(backIcon),
onPressed: _handleBackButton,
tooltip: 'Back' // TODO(ianh): Figure out how to localize this string
);
}
if (_canPop)
leading = const BackButton();
}
}
if (leading != null) {
......
// 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/widgets.dart';
import 'theme.dart';
import 'icon_button.dart';
import 'icon.dart';
import 'icons.dart';
/// A material design back button.
///
/// A [BackButton] is an [IconButton] with a "back" icon appropriate for the
/// current [TargetPlatform]. When pressed, the back button calls
/// [Navigator.maybePop] to return to the previous route.
///
/// When deciding to display a [BackButton], consider using
/// `ModalRoute.of(context)?.canPop` to check whether the current route can be
/// popped. If that value is false (e.g., because the current route is the
/// initial route), the [BackButton] will not have any effect when pressed,
/// which could frustrate the user.
///
/// Requires one of its ancestors to be a [Material] widget.
///
/// See also:
///
/// * [AppBar], which automatically uses a [BackButton] in its
/// [AppBar.leading] slot when appropriate.
/// * [IconButton], which is a more general widget for creating buttons with
/// icons.
class BackButton extends StatelessWidget {
/// Creates an [IconButton] with the appropriate "back" icon for the current
/// target platform.
const BackButton({ Key key }) : super(key: key);
/// Returns tha appropriate "back" icon for the given `platform`.
static IconData getIconData(TargetPlatform platform) {
switch (platform) {
case TargetPlatform.android:
case TargetPlatform.fuchsia:
return Icons.arrow_back;
case TargetPlatform.iOS:
return Icons.arrow_back_ios;
}
assert(false);
return null;
}
@override
Widget build(BuildContext context) {
return new IconButton(
icon: new Icon(getIconData(Theme.of(context).platform)),
tooltip: 'Back', // TODO(ianh): Figure out how to localize this string
onPressed: () {
Navigator.of(context).maybePop();
},
);
}
}
// Copyright 2016 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/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('BackButton control test', (WidgetTester tester) async {
await tester.pumpWidget(
new MaterialApp(
home: new Material(child: new Text('Home')),
routes: <String, WidgetBuilder>{
'/next': (BuildContext context) {
return new Material(
child: new Center(
child: const BackButton(),
)
);
},
}
)
);
tester.state<NavigatorState>(find.byType(Navigator)).pushNamed('/next');
await tester.pump();
await tester.pumpUntilNoTransientCallbacks();
await tester.tap(find.byType(BackButton));
await tester.pump();
await tester.pumpUntilNoTransientCallbacks();
expect(find.text('Home'), findsOneWidget);
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment