Added AppBarBehavior.under, etc
diff --git a/examples/material_gallery/lib/demo/flexible_space_demo.dart b/examples/material_gallery/lib/demo/flexible_space_demo.dart
index 0282dbe..ec7eab3 100644
--- a/examples/material_gallery/lib/demo/flexible_space_demo.dart
+++ b/examples/material_gallery/lib/demo/flexible_space_demo.dart
@@ -72,8 +72,10 @@
 }
 
 class FlexibleSpaceDemoState extends State<FlexibleSpaceDemo> {
+  final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
   final double appBarHeight = 256.0;
   final Key scrollableKey = new UniqueKey();
+  AppBarBehavior _appBarBehavior = AppBarBehavior.scroll;
 
   Widget build(BuildContext context) {
     return new Theme(
@@ -82,18 +84,37 @@
         primarySwatch: Colors.indigo
       ),
       child: new Scaffold(
+        key: scaffoldKey,
         appBarHeight: appBarHeight,
         scrollableKey: scrollableKey,
-        appBarBehavior: AppBarBehavior.scroll,
+        appBarBehavior: _appBarBehavior,
         appBar: new AppBar(
           actions: <Widget>[
             new IconButton(
               icon: Icons.create,
-              tooltip: 'Search'
+              tooltip: 'Search',
+              onPressed: () {
+                scaffoldKey.currentState.showSnackBar(new SnackBar(
+                  content: new Text('Not supported.')
+                ));
+              }
             ),
-            new IconButton(
-              icon: Icons.more_vert,
-              tooltip: 'Show menu'
+            new PopupMenuButton<AppBarBehavior>(
+              onSelected: (AppBarBehavior value) {
+                setState(() {
+                  _appBarBehavior = value;
+                });
+              },
+              items: <PopupMenuItem<AppBarBehavior>>[
+                new PopupMenuItem<AppBarBehavior>(
+                  value: AppBarBehavior.scroll,
+                  child: new Text('AppBar scrolls away')
+                ),
+                new PopupMenuItem<AppBarBehavior>(
+                  value: AppBarBehavior.under,
+                  child: new Text('AppBar stays put')
+                )
+              ]
             )
           ],
           flexibleSpace: (BuildContext context) {
diff --git a/examples/material_gallery/lib/gallery/section.dart b/examples/material_gallery/lib/gallery/section.dart
index c1060f1..2670c2d 100644
--- a/examples/material_gallery/lib/gallery/section.dart
+++ b/examples/material_gallery/lib/gallery/section.dart
@@ -37,7 +37,7 @@
           data: theme,
           child: new Scaffold(
             appBarHeight: appBarHeight,
-            appBarBehavior: AppBarBehavior.scroll,
+            appBarBehavior: AppBarBehavior.under,
             scrollableKey: scrollableKey,
             appBar: new AppBar(
               flexibleSpace: (BuildContext context) => new FlexibleSpaceBar(title: new Text(title))
diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart
index d478d6e..596bcd8 100644
--- a/packages/flutter/lib/src/material/app_bar.dart
+++ b/packages/flutter/lib/src/material/app_bar.dart
@@ -117,7 +117,7 @@
 
     // If the toolBar's height shrinks below toolBarHeight, it will be clipped and bottom
     // justified. This is so that the toolbar appears to move upwards as its height is reduced.
-    final double toolBarHeight = kAppBarHeight + combinedPadding.top + combinedPadding.bottom;
+    final double toolBarHeight = kToolBarHeight + combinedPadding.top + combinedPadding.bottom;
     final Widget toolBar = new ConstrainedBox(
       constraints: new BoxConstraints(maxHeight: toolBarHeight),
       child: new Padding(
diff --git a/packages/flutter/lib/src/material/constants.dart b/packages/flutter/lib/src/material/constants.dart
index 93f37f0..f56f506 100644
--- a/packages/flutter/lib/src/material/constants.dart
+++ b/packages/flutter/lib/src/material/constants.dart
@@ -9,7 +9,7 @@
 // Mobile Landscape: 48dp
 // Mobile Portrait: 56dp
 // Tablet/Desktop: 64dp
-const double kAppBarHeight = 56.0;
+const double kToolBarHeight = 56.0;
 const double kExtendedAppBarHeight = 128.0;
 
 const double kTextTabBarHeight = 48.0;
diff --git a/packages/flutter/lib/src/material/flexible_space_bar.dart b/packages/flutter/lib/src/material/flexible_space_bar.dart
index b9d4408..f61b63e 100644
--- a/packages/flutter/lib/src/material/flexible_space_bar.dart
+++ b/packages/flutter/lib/src/material/flexible_space_bar.dart
@@ -27,7 +27,7 @@
     final double appBarHeight = Scaffold.of(context).appBarHeight;
     final Animation<double> animation = Scaffold.of(context).appBarAnimation;
     final EdgeInsets toolBarPadding = MediaQuery.of(context)?.padding ?? EdgeInsets.zero;
-    final double toolBarHeight = kAppBarHeight + toolBarPadding.top;
+    final double toolBarHeight = kToolBarHeight + toolBarPadding.top;
     final List<Widget> children = <Widget>[];
 
     // background image
@@ -63,7 +63,7 @@
         color: titleStyle.color.withAlpha(new Tween<double>(begin: 255.0, end: 0.0).evaluate(opacityCurve).toInt())
       );
       final double yAlignStart = 1.0;
-      final double yAlignEnd = (toolBarPadding.top + kAppBarHeight / 2.0) / toolBarHeight;
+      final double yAlignEnd = (toolBarPadding.top + kToolBarHeight / 2.0) / toolBarHeight;
       final double scaleAndAlignEnd = (appBarHeight - toolBarHeight) / appBarHeight;
       final CurvedAnimation scaleAndAlignCurve = new CurvedAnimation(
         parent: animation,
diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart
index 8cb699d..954d3de 100644
--- a/packages/flutter/lib/src/material/scaffold.dart
+++ b/packages/flutter/lib/src/material/scaffold.dart
@@ -20,9 +20,25 @@
 const double _kFloatingActionButtonMargin = 16.0; // TODO(hmuller): should be device dependent
 const Duration _kFloatingActionButtonSegue = const Duration(milliseconds: 400);
 
+/// The Scaffold's appbar is the toolbar, tabbar, and the "flexible space" that's
+/// stacked behind them. The Scaffold's appBarBehavior defines how the appbar
+/// responds to scrolling the application.
 enum AppBarBehavior {
+  /// The tool bar's layout does not respond to scrolling.
   anchor,
+
+  /// The tool bar's appearance and layout depend on the scrollOffset of the
+  /// Scrollable identified by the Scaffold's scrollableKey. With the scrollOffset
+  /// at 0.0, scrolling downwards causes the toolbar's flexible space to shrink,
+  /// and then the entire toolbar fade outs and scrolls off the top of the screen.
+  /// Scrolling upwards always causes the toolbar to reappear.
   scroll,
+
+  /// The tool bar's appearance and layout depend on the scrollOffset of the
+  /// Scrollable identified by the Scaffold's scrollableKey. With the scrollOffset
+  /// at 0.0, Scrolling downwards causes the toolbar's flexible space to shrink.
+  /// Other than that, the toolbar remains anchored at the top.
+  under,
 }
 
 enum _ScaffoldSlot {
@@ -192,7 +208,7 @@
     this.appBarHeight
   }) : super(key: key) {
     assert((appBarBehavior == AppBarBehavior.scroll) ? scrollableKey != null : true);
-    assert((appBarBehavior == AppBarBehavior.scroll) ? appBarHeight != null && appBarHeight > kAppBarHeight : true);
+    assert((appBarBehavior == AppBarBehavior.scroll) ? appBarHeight != null && appBarHeight > kToolBarHeight : true);
   }
 
   final AppBar appBar;
@@ -430,36 +446,53 @@
     ));
   }
 
+  Widget _buildAnchoredAppBar(double toolBarHeight, EdgeInsets toolBarPadding) {
+    // Drive _appBarController to the point where the flexible space has disappeared.
+    _appBarController.value = (appBarHeight - toolBarHeight) / appBarHeight;
+    return new SizedBox(
+      height: toolBarHeight,
+      child: _getModifiedAppBar(padding: toolBarPadding)
+    );
+  }
+
   Widget _buildScrollableAppBar(BuildContext context) {
-    final EdgeInsets appBarPadding = MediaQuery.of(context)?.padding ?? EdgeInsets.zero;
-    final double appBarHeight = kAppBarHeight + appBarPadding.top;
+    final EdgeInsets toolBarPadding = MediaQuery.of(context)?.padding ?? EdgeInsets.zero;
+    final double toolBarHeight = kToolBarHeight + toolBarPadding.top;
     Widget appBar;
 
-    if (_scrollOffset <= appBarHeight && _scrollOffset >= appBarHeight - appBarHeight) {
-      // scrolled to the top, only the app bar is (partially) visible
-      final double height = math.max(_floatingAppBarHeight, appBarHeight - _scrollOffset);
-      final double opacity = _appBarOpacity(1.0 - ((appBarHeight - height) / appBarHeight));
-      _appBarController.value = (appBarHeight - height) / appBarHeight;
-      appBar = new SizedBox(
-        height: height,
-        child: _getModifiedAppBar(padding: appBarPadding, foregroundOpacity: opacity)
-      );
+    if (_scrollOffset <= appBarHeight && _scrollOffset >= appBarHeight - toolBarHeight) {
+      // scrolled to the top, only the toolbar is (partially) visible.
+      if (config.appBarBehavior == AppBarBehavior.under) {
+        appBar = _buildAnchoredAppBar(toolBarHeight, toolBarPadding);
+      } else {
+        final double height = math.max(_floatingAppBarHeight, appBarHeight - _scrollOffset);
+        final double opacity = _appBarOpacity(1.0 - ((toolBarHeight - height) / toolBarHeight));
+        _appBarController.value = (appBarHeight - height) / appBarHeight;
+        appBar = new SizedBox(
+          height: height,
+          child: _getModifiedAppBar(padding: toolBarPadding, foregroundOpacity: opacity)
+        );
+      }
     } else if (_scrollOffset > appBarHeight) {
-      // scrolled down, show the "floating" app bar
-      _floatingAppBarHeight = (_floatingAppBarHeight + _scrollOffsetDelta).clamp(0.0, appBarHeight);
-      final double appBarOpacity = _appBarOpacity(_floatingAppBarHeight / appBarHeight);
-      _appBarController.value = (appBarHeight - _floatingAppBarHeight) / appBarHeight;
-      appBar = new SizedBox(
-        height: _floatingAppBarHeight,
-        child: _getModifiedAppBar(padding: appBarPadding, foregroundOpacity: appBarOpacity)
-      );
+      // scrolled past the entire app bar, maybe show the "floating" toolbar.
+      if (config.appBarBehavior == AppBarBehavior.under) {
+        appBar = _buildAnchoredAppBar(toolBarHeight, toolBarPadding);
+      } else {
+        _floatingAppBarHeight = (_floatingAppBarHeight + _scrollOffsetDelta).clamp(0.0, toolBarHeight);
+        final double toolBarOpacity = _appBarOpacity(_floatingAppBarHeight / toolBarHeight);
+        _appBarController.value = (appBarHeight - _floatingAppBarHeight) / appBarHeight;
+        appBar = new SizedBox(
+          height: _floatingAppBarHeight,
+          child: _getModifiedAppBar(padding: toolBarPadding, foregroundOpacity: toolBarOpacity)
+        );
+      }
     } else {
       // _scrollOffset < appBarHeight - appBarHeight, scrolled to the top, flexible space is visible
       final double height = appBarHeight - _scrollOffset.clamp(0.0, appBarHeight);
       _appBarController.value = (appBarHeight - height) / appBarHeight;
       appBar = new SizedBox(
         height: height,
-        child: _getModifiedAppBar(padding: appBarPadding, elevation: 0)
+        child: _getModifiedAppBar(padding: toolBarPadding, elevation: 0)
       );
       _floatingAppBarHeight = 0.0;
     }
@@ -468,10 +501,10 @@
   }
 
   Widget build(BuildContext context) {
-    EdgeInsets padding = MediaQuery.of(context)?.padding ?? EdgeInsets.zero;
+    final EdgeInsets padding = MediaQuery.of(context)?.padding ?? EdgeInsets.zero;
 
     if (_snackBars.length > 0) {
-      ModalRoute<dynamic> route = ModalRoute.of(context);
+      final ModalRoute<dynamic> route = ModalRoute.of(context);
       if (route == null || route.isCurrent) {
         if (_snackBarController.isCompleted && _snackBarTimer == null)
           _snackBarTimer = new Timer(_snackBars.first._widget.duration, _hideSnackBar);
@@ -484,7 +517,7 @@
     final List<LayoutId> children = new List<LayoutId>();
     _addIfNonNull(children, config.body, _ScaffoldSlot.body);
     if (config.appBarBehavior == AppBarBehavior.anchor) {
-      Widget appBar = new ConstrainedBox(
+      final Widget appBar = new ConstrainedBox(
         child: _getModifiedAppBar(padding: padding),
         constraints: new BoxConstraints(maxHeight: config.appBarHeight ?? kExtendedAppBarHeight + padding.top)
       );
@@ -494,7 +527,7 @@
 
     if (_currentBottomSheet != null ||
         (_dismissedBottomSheets != null && _dismissedBottomSheets.isNotEmpty)) {
-      List<Widget> bottomSheets = <Widget>[];
+      final List<Widget> bottomSheets = <Widget>[];
       if (_dismissedBottomSheets != null && _dismissedBottomSheets.isNotEmpty)
         bottomSheets.addAll(_dismissedBottomSheets);
       if (_currentBottomSheet != null)
@@ -510,7 +543,7 @@
       _addIfNonNull(children, _snackBars.first._widget, _ScaffoldSlot.snackBar);
 
     if (config.floatingActionButton != null) {
-      Widget fab = new _FloatingActionButtonTransition(
+      final Widget fab = new _FloatingActionButtonTransition(
         key: new ValueKey<Key>(config.floatingActionButton.key),
         child: config.floatingActionButton
       );
@@ -529,8 +562,7 @@
 
     Widget application;
 
-    if (config.appBarBehavior == AppBarBehavior.scroll) {
-      double overScroll = _scrollOffset.clamp(double.NEGATIVE_INFINITY, 0.0);
+    if (config.appBarBehavior != AppBarBehavior.anchor) {
       application = new NotificationListener<ScrollNotification>(
         onNotification: _handleScrollNotification,
         child: new Stack(
@@ -542,7 +574,7 @@
               )
             ),
             new Positioned(
-              top: -overScroll,
+              top: 0.0,
               left: 0.0,
               right: 0.0,
               child: _buildScrollableAppBar(context)
diff --git a/packages/flutter/lib/src/widgets/scrollable_list.dart b/packages/flutter/lib/src/widgets/scrollable_list.dart
index 5641b1e..b8bfbdc 100644
--- a/packages/flutter/lib/src/widgets/scrollable_list.dart
+++ b/packages/flutter/lib/src/widgets/scrollable_list.dart
@@ -45,7 +45,7 @@
 }
 
 class _ScrollableListState extends ScrollableState<ScrollableList> {
-  ScrollBehavior<double, double> createScrollBehavior() => new OverscrollBehavior();
+  ScrollBehavior<double, double> createScrollBehavior() => new OverscrollWhenScrollableBehavior();
   ExtentScrollBehavior get scrollBehavior => super.scrollBehavior;
 
   void _handleExtentsChanged(double contentExtent, double containerExtent) {