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
This commit is contained in:
parent
17057bb44b
commit
fcf6740851
@ -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) {
|
||||
|
60
packages/flutter/lib/src/material/back_button.dart
Normal file
60
packages/flutter/lib/src/material/back_button.dart
Normal file
@ -0,0 +1,60 @@
|
||||
// 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();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
37
packages/flutter/test/material/back_button_test.dart
Normal file
37
packages/flutter/test/material/back_button_test.dart
Normal file
@ -0,0 +1,37 @@
|
||||
// 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);
|
||||
});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user