Make drawer demo header not scroll away (#13337)
* Make drawer demo header not scroll
* Add test for gallery drawer demo and fix user accounts drawer header overflow
diff --git a/examples/flutter_gallery/ios/Runner.xcodeproj/project.pbxproj b/examples/flutter_gallery/ios/Runner.xcodeproj/project.pbxproj
index dbff9d2..21acc356 100644
--- a/examples/flutter_gallery/ios/Runner.xcodeproj/project.pbxproj
+++ b/examples/flutter_gallery/ios/Runner.xcodeproj/project.pbxproj
@@ -276,12 +276,18 @@
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../../../../bin/cache/artifacts/engine/ios/Flutter.framework",
+ "${BUILT_PRODUCTS_DIR}/Reachability/Reachability.framework",
+ "${BUILT_PRODUCTS_DIR}/connectivity/connectivity.framework",
"${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework",
+ "${BUILT_PRODUCTS_DIR}/video_player/video_player.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reachability.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -508,4 +514,4 @@
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
-}
\ No newline at end of file
+}
diff --git a/examples/flutter_gallery/lib/demo/material/drawer_demo.dart b/examples/flutter_gallery/lib/demo/material/drawer_demo.dart
index f35f1b0..7eaa46c 100644
--- a/examples/flutter_gallery/lib/demo/material/drawer_demo.dart
+++ b/examples/flutter_gallery/lib/demo/material/drawer_demo.dart
@@ -89,7 +89,7 @@
title: const Text('Navigation drawer'),
),
drawer: new Drawer(
- child: new ListView(
+ child: new Column(
children: <Widget>[
new UserAccountsDrawerHeader(
accountName: const Text('Zach Widget'),
@@ -114,6 +114,7 @@
),
),
],
+ margin: EdgeInsets.zero,
onDetailsPressed: () {
_showDrawerContents = !_showDrawerContents;
if (_showDrawerContents)
@@ -122,48 +123,58 @@
_controller.forward();
},
),
- new ClipRect(
- child: new Stack(
- children: <Widget>[
- // The initial contents of the drawer.
- new FadeTransition(
- opacity: _drawerContentsOpacity,
- child: new Column(
- mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.stretch,
- children: _drawerContents.map((String id) {
- return new ListTile(
- leading: new CircleAvatar(child: new Text(id)),
- title: new Text('Drawer item $id'),
- onTap: _showNotImplementedMessage,
- );
- }).toList(),
- ),
- ),
- // The drawer's "details" view.
- new SlideTransition(
- position: _drawerDetailsPosition,
- child: new FadeTransition(
- opacity: new ReverseAnimation(_drawerContentsOpacity),
- child: new Column(
- mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.stretch,
- children: <Widget>[
- new ListTile(
- leading: const Icon(Icons.add),
- title: const Text('Add account'),
- onTap: _showNotImplementedMessage,
+ new MediaQuery.removePadding(
+ context: context,
+ // DrawerHeader consumes top MediaQuery padding.
+ removeTop: true,
+ child: new Expanded(
+ child: new ListView(
+ padding: const EdgeInsets.only(top: 8.0),
+ children: <Widget>[
+ new Stack(
+ children: <Widget>[
+ // The initial contents of the drawer.
+ new FadeTransition(
+ opacity: _drawerContentsOpacity,
+ child: new Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: _drawerContents.map((String id) {
+ return new ListTile(
+ leading: new CircleAvatar(child: new Text(id)),
+ title: new Text('Drawer item $id'),
+ onTap: _showNotImplementedMessage,
+ );
+ }).toList(),
),
- new ListTile(
- leading: const Icon(Icons.settings),
- title: const Text('Manage accounts'),
- onTap: _showNotImplementedMessage,
+ ),
+ // The drawer's "details" view.
+ new SlideTransition(
+ position: _drawerDetailsPosition,
+ child: new FadeTransition(
+ opacity: new ReverseAnimation(_drawerContentsOpacity),
+ child: new Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: <Widget>[
+ new ListTile(
+ leading: const Icon(Icons.add),
+ title: const Text('Add account'),
+ onTap: _showNotImplementedMessage,
+ ),
+ new ListTile(
+ leading: const Icon(Icons.settings),
+ title: const Text('Manage accounts'),
+ onTap: _showNotImplementedMessage,
+ ),
+ ],
+ ),
),
- ],
- ),
+ ),
+ ],
),
- ),
- ],
+ ],
+ ),
),
),
],
diff --git a/examples/flutter_gallery/test/demo/material/drawer_demo_test.dart b/examples/flutter_gallery/test/demo/material/drawer_demo_test.dart
new file mode 100644
index 0000000..eb3545b
--- /dev/null
+++ b/examples/flutter_gallery/test/demo/material/drawer_demo_test.dart
@@ -0,0 +1,31 @@
+// 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/material.dart';
+import 'package:flutter_gallery/demo/material/drawer_demo.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ testWidgets('Drawer header does not scroll', (WidgetTester tester) async {
+ await tester.pumpWidget(new MaterialApp(
+ theme: new ThemeData(platform: TargetPlatform.iOS),
+ home: new DrawerDemo(),
+ ));
+
+ await tester.tap(find.text('Tap here to open the drawer'));
+ await tester.pump();
+ await tester.pump(const Duration(milliseconds: 500));
+
+ expect(tester.getTopLeft(find.byType(UserAccountsDrawerHeader)).dy, 0.0);
+ final double initialTopItemSaneY = tester.getTopLeft(find.text('Drawer item A')).dy;
+ expect(initialTopItemSaneY, greaterThan(0.0));
+
+ await tester.drag(find.text('Drawer item B'), const Offset(0.0, 400.0));
+ await tester.pump();
+
+ expect(tester.getTopLeft(find.byType(UserAccountsDrawerHeader)).dy, 0.0);
+ expect(tester.getTopLeft(find.text('Drawer item A')).dy, greaterThan(initialTopItemSaneY));
+ expect(tester.getTopLeft(find.text('Drawer item A')).dy, lessThanOrEqualTo(initialTopItemSaneY + 400.0));
+ });
+}
diff --git a/packages/flutter/lib/src/material/user_accounts_drawer_header.dart b/packages/flutter/lib/src/material/user_accounts_drawer_header.dart
index d497a41..713849a 100644
--- a/packages/flutter/lib/src/material/user_accounts_drawer_header.dart
+++ b/packages/flutter/lib/src/material/user_accounts_drawer_header.dart
@@ -68,18 +68,18 @@
final bool isOpen;
Widget addDropdownIcon(Widget line) {
- final Widget icon = new Expanded(
- child: new Align(
- alignment: AlignmentDirectional.centerEnd,
- child: new Icon(
- isOpen ? Icons.arrow_drop_up : Icons.arrow_drop_down,
- color: Colors.white
- ),
- ),
+ final Widget icon = new Icon(
+ isOpen ? Icons.arrow_drop_up : Icons.arrow_drop_down,
+ color: Colors.white
);
- return new Row(
- crossAxisAlignment: CrossAxisAlignment.center,
- children: line == null ? <Widget>[icon] : <Widget>[line, icon],
+ return new Expanded(
+ child: new Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: line == null ? <Widget>[icon] : <Widget>[
+ new Expanded(child: line),
+ icon,
+ ],
+ ),
);
}
@@ -88,10 +88,12 @@
final ThemeData theme = Theme.of(context);
Widget accountNameLine = accountName == null ? null : new DefaultTextStyle(
style: theme.primaryTextTheme.body2,
+ overflow: TextOverflow.ellipsis,
child: accountName,
);
Widget accountEmailLine = accountEmail == null ? null : new DefaultTextStyle(
style: theme.primaryTextTheme.body1,
+ overflow: TextOverflow.ellipsis,
child: accountEmail,
);
if (onTap != null) {