Commit 2d6f268d authored by xster's avatar xster Committed by Todd Volkert

Revert "Let translucent Cupertino bars have its scaffold children...

Revert "Let translucent Cupertino bars have its scaffold children automatically pad their heights (#13194)" (#13317)

This reverts commit 5c4ffa13.
parent 6db83307
...@@ -131,21 +131,17 @@ class CupertinoDemoTab1 extends StatelessWidget { ...@@ -131,21 +131,17 @@ class CupertinoDemoTab1 extends StatelessWidget {
largeTitle: const Text('Colors'), largeTitle: const Text('Colors'),
trailing: const ExitButton(), trailing: const ExitButton(),
), ),
new SliverPadding( new SliverList(
// Top media query padding already consumed by CupertinoSliverNavigationBar. delegate: new SliverChildBuilderDelegate(
padding: MediaQuery.of(context).removePadding(removeTop: true).padding, (BuildContext context, int index) {
sliver: new SliverList( return new Tab1RowItem(
delegate: new SliverChildBuilderDelegate( index: index,
(BuildContext context, int index) { lastItem: index == 49,
return new Tab1RowItem( color: colorItems[index],
index: index, colorName: colorNameItems[index],
lastItem: index == 49, );
color: colorItems[index], },
colorName: colorNameItems[index], childCount: 50,
);
},
childCount: 50,
),
), ),
), ),
], ],
...@@ -275,7 +271,7 @@ class Tab1ItemPageState extends State<Tab1ItemPage> { ...@@ -275,7 +271,7 @@ class Tab1ItemPageState extends State<Tab1ItemPage> {
), ),
child: new ListView( child: new ListView(
children: <Widget>[ children: <Widget>[
const Padding(padding: const EdgeInsets.only(top: 16.0)), const Padding(padding: const EdgeInsets.only(top: 80.0)),
new Padding( new Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0), padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: new Row( child: new Row(
...@@ -400,6 +396,7 @@ class CupertinoDemoTab2 extends StatelessWidget { ...@@ -400,6 +396,7 @@ class CupertinoDemoTab2 extends StatelessWidget {
), ),
child: new ListView( child: new ListView(
children: <Widget>[ children: <Widget>[
const Padding(padding: const EdgeInsets.only(top: 60.0)),
new Tab2Header(), new Tab2Header(),
]..addAll(buildTab2Conversation()), ]..addAll(buildTab2Conversation()),
), ),
...@@ -667,6 +664,7 @@ List<Widget> buildTab2Conversation() { ...@@ -667,6 +664,7 @@ List<Widget> buildTab2Conversation() {
const Tab2ConversationRow( const Tab2ConversationRow(
text: "What's that?", text: "What's that?",
), ),
const Padding(padding: const EdgeInsets.only(bottom: 80.0)),
]; ];
} }
...@@ -682,7 +680,7 @@ class CupertinoDemoTab3 extends StatelessWidget { ...@@ -682,7 +680,7 @@ class CupertinoDemoTab3 extends StatelessWidget {
decoration: const BoxDecoration(color: const Color(0xFFEFEFF4)), decoration: const BoxDecoration(color: const Color(0xFFEFEFF4)),
child: new ListView( child: new ListView(
children: <Widget>[ children: <Widget>[
const Padding(padding: const EdgeInsets.only(top: 32.0)), const Padding(padding: const EdgeInsets.only(top: 100.0)),
new GestureDetector( new GestureDetector(
onTap: () { onTap: () {
Navigator.of(context, rootNavigator: true).push( Navigator.of(context, rootNavigator: true).push(
......
...@@ -11,7 +11,6 @@ import 'package:flutter/widgets.dart'; ...@@ -11,7 +11,6 @@ import 'package:flutter/widgets.dart';
import 'button.dart'; import 'button.dart';
import 'colors.dart'; import 'colors.dart';
import 'icons.dart'; import 'icons.dart';
import 'page_scaffold.dart';
/// Standard iOS navigation bar height without the status bar. /// Standard iOS navigation bar height without the status bar.
const double _kNavBarPersistentHeight = 44.0; const double _kNavBarPersistentHeight = 44.0;
...@@ -69,7 +68,7 @@ const TextStyle _kLargeTitleTextStyle = const TextStyle( ...@@ -69,7 +68,7 @@ const TextStyle _kLargeTitleTextStyle = const TextStyle(
/// [CupertinoNavigationBar]. /// [CupertinoNavigationBar].
/// * [CupertinoSliverNavigationBar] for a navigation bar to be placed in a /// * [CupertinoSliverNavigationBar] for a navigation bar to be placed in a
/// scrolling list and that supports iOS-11-style large titles. /// scrolling list and that supports iOS-11-style large titles.
class CupertinoNavigationBar extends StatelessWidget implements ObstructingPreferredSizeWidget { class CupertinoNavigationBar extends StatelessWidget implements PreferredSizeWidget {
/// Creates a navigation bar in the iOS style. /// Creates a navigation bar in the iOS style.
const CupertinoNavigationBar({ const CupertinoNavigationBar({
Key key, Key key,
...@@ -117,12 +116,11 @@ class CupertinoNavigationBar extends StatelessWidget implements ObstructingPrefe ...@@ -117,12 +116,11 @@ class CupertinoNavigationBar extends StatelessWidget implements ObstructingPrefe
final Color actionsForegroundColor; final Color actionsForegroundColor;
/// True if the navigation bar's background color has no transparency. /// True if the navigation bar's background color has no transparency.
@override bool get opaque => backgroundColor.alpha == 0xFF;
bool get fullObstruction => backgroundColor.alpha == 0xFF;
@override @override
Size get preferredSize { Size get preferredSize {
return const Size.fromHeight(_kNavBarPersistentHeight); return opaque ? const Size.fromHeight(_kNavBarPersistentHeight) : Size.zero;
} }
@override @override
......
...@@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart'; ...@@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'colors.dart'; import 'colors.dart';
import 'nav_bar.dart';
/// Implements a single iOS application page's layout. /// Implements a single iOS application page's layout.
/// ///
...@@ -31,52 +32,41 @@ class CupertinoPageScaffold extends StatelessWidget { ...@@ -31,52 +32,41 @@ class CupertinoPageScaffold extends StatelessWidget {
/// ///
/// If translucent, the main content may slide behind it. /// If translucent, the main content may slide behind it.
/// Otherwise, the main content's top margin will be offset by its height. /// Otherwise, the main content's top margin will be offset by its height.
///
/// The scaffold assumes the nav bar will consume the [MediaQuery] top padding.
// TODO(xster): document its page transition animation when ready // TODO(xster): document its page transition animation when ready
final ObstructingPreferredSizeWidget navigationBar; final PreferredSizeWidget navigationBar;
/// Widget to show in the main content area. /// Widget to show in the main content area.
/// ///
/// Content can slide under the [navigationBar] when they're translucent with /// Content can slide under the [navigationBar] when they're translucent.
/// a [MediaQuery] padding hinting the top obstructed area.
final Widget child; final Widget child;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final List<Widget> stacked = <Widget>[]; final List<Widget> stacked = <Widget>[];
Widget childWithMediaQuery = child;
Widget paddedContent = child; double topPadding = 0.0;
if (navigationBar != null) { if (navigationBar != null) {
final MediaQueryData existingMediaQuery = MediaQuery.of(context); topPadding += navigationBar.preferredSize.height;
// If the navigation bar has a preferred size, pad it and the OS status
// TODO(https://github.com/flutter/flutter/issues/12912): // bar as well. Otherwise, let the content extend to the complete top
// Use real size after partial layout instead of preferred size. // of the page.
final double topPadding = navigationBar.preferredSize.height if (topPadding > 0.0) {
+ existingMediaQuery.padding.top; final EdgeInsets mediaQueryPadding = MediaQuery.of(context).padding;
topPadding += mediaQueryPadding.top;
// If nav bar is opaquely obstructing, directly shift the main content childWithMediaQuery = new MediaQuery.removePadding(
// down. If translucent, let main content draw behind nav bar but hint the context: context,
// obstructed area. removeTop: true,
if (navigationBar.fullObstruction) {
paddedContent = new Padding(
padding: new EdgeInsets.only(top: topPadding),
child: child,
);
} else {
paddedContent = new MediaQuery(
data: existingMediaQuery.copyWith(
padding: existingMediaQuery.padding.copyWith(
top: topPadding,
),
),
child: child, child: child,
); );
} }
} }
// The main content being at the bottom is added to the stack first. // The main content being at the bottom is added to the stack first.
stacked.add(paddedContent); stacked.add(new Padding(
padding: new EdgeInsets.only(top: topPadding),
child: childWithMediaQuery,
));
if (navigationBar != null) { if (navigationBar != null) {
stacked.add(new Positioned( stacked.add(new Positioned(
...@@ -94,14 +84,4 @@ class CupertinoPageScaffold extends StatelessWidget { ...@@ -94,14 +84,4 @@ class CupertinoPageScaffold extends StatelessWidget {
), ),
); );
} }
} }
\ No newline at end of file
/// Widget that has a preferred size and reports whether it fully obstructs
/// widgets behind it.
abstract class ObstructingPreferredSizeWidget extends PreferredSizeWidget {
/// If true, this widget fully obstructs widgets behind it by the specified
/// size.
///
/// If false, this widget partially obstructs.
bool get fullObstruction;
}
...@@ -117,8 +117,7 @@ class CupertinoTabScaffold extends StatefulWidget { ...@@ -117,8 +117,7 @@ class CupertinoTabScaffold extends StatefulWidget {
/// When the tab becomes inactive, its content is still cached in the widget /// When the tab becomes inactive, its content is still cached in the widget
/// tree [Offstage] and its animations disabled. /// tree [Offstage] and its animations disabled.
/// ///
/// Content can slide under the [tabBar] when it's translucent with a /// Content can slide under the [tabBar] when it's translucent.
/// [MediaQuery] padding hinting the bottom obstructed area.
final IndexedWidgetBuilder tabBuilder; final IndexedWidgetBuilder tabBuilder;
@override @override
...@@ -132,42 +131,17 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> { ...@@ -132,42 +131,17 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final List<Widget> stacked = <Widget>[]; final List<Widget> stacked = <Widget>[];
Widget content = new _TabView(
currentTabIndex: _currentPage,
tabNumber: widget.tabBar.items.length,
tabBuilder: widget.tabBuilder,
);
if (widget.tabBar != null) {
final MediaQueryData existingMediaQuery = MediaQuery.of(context);
// TODO(https://github.com/flutter/flutter/issues/12912):
// Use real size after partial layout instead of preferred size.
final double bottomPadding = widget.tabBar.preferredSize.height
+ existingMediaQuery.padding.bottom;
// If tab bar opaque, directly stop the main content higher. If
// translucent, let main content draw behind the tab bar but hint the
// obstructed area.
if (widget.tabBar.opaque) {
content = new Padding(
padding: new EdgeInsets.only(bottom: bottomPadding),
child: content,
);
} else {
content = new MediaQuery(
data: existingMediaQuery.copyWith(
padding: existingMediaQuery.padding.copyWith(
bottom: bottomPadding,
),
),
child: content,
);
}
}
// The main content being at the bottom is added to the stack first. // The main content being at the bottom is added to the stack first.
stacked.add(content); stacked.add(
new Padding(
padding: new EdgeInsets.only(bottom: widget.tabBar.opaque ? widget.tabBar.preferredSize.height : 0.0),
child: new _TabView(
currentTabIndex: _currentPage,
tabNumber: widget.tabBar.items.length,
tabBuilder: widget.tabBuilder,
)
),
);
if (widget.tabBar != null) { if (widget.tabBar != null) {
stacked.add(new Align( stacked.add(new Align(
......
...@@ -7,7 +7,6 @@ import 'package:flutter/rendering.dart'; ...@@ -7,7 +7,6 @@ import 'package:flutter/rendering.dart';
import 'basic.dart'; import 'basic.dart';
import 'framework.dart'; import 'framework.dart';
import 'media_query.dart';
import 'primary_scroll_controller.dart'; import 'primary_scroll_controller.dart';
import 'scroll_controller.dart'; import 'scroll_controller.dart';
import 'scroll_physics.dart'; import 'scroll_physics.dart';
...@@ -373,33 +372,8 @@ abstract class BoxScrollView extends ScrollView { ...@@ -373,33 +372,8 @@ abstract class BoxScrollView extends ScrollView {
@override @override
List<Widget> buildSlivers(BuildContext context) { List<Widget> buildSlivers(BuildContext context) {
Widget sliver = buildChildLayout(context); Widget sliver = buildChildLayout(context);
EdgeInsetsGeometry effectivePadding = padding; if (padding != null)
if (padding == null) { sliver = new SliverPadding(padding: padding, sliver: sliver);
final MediaQueryData mediaQuery = MediaQuery.of(context, nullOk: true);
if (mediaQuery != null) {
// Automatically pad sliver with padding from MediaQuery.
final EdgeInsets mediaQueryHorizontalPadding =
mediaQuery.padding.copyWith(top: 0.0, bottom: 0.0);
final EdgeInsets mediaQueryVerticalPadding =
mediaQuery.padding.copyWith(left: 0.0, right: 0.0);
// Consume the main axis padding with SliverPadding.
effectivePadding = scrollDirection == Axis.vertical
? mediaQueryVerticalPadding
: mediaQueryHorizontalPadding;
// Leave behind the cross axis padding.
sliver = new MediaQuery(
data: mediaQuery.copyWith(
padding: scrollDirection == Axis.vertical
? mediaQueryHorizontalPadding
: mediaQueryVerticalPadding,
),
child: sliver,
);
}
}
if (effectivePadding != null)
sliver = new SliverPadding(padding: effectivePadding, sliver: sliver);
return <Widget>[ sliver ]; return <Widget>[ sliver ];
} }
......
...@@ -78,66 +78,6 @@ void main() { ...@@ -78,66 +78,6 @@ void main() {
expect(tester.getSize(find.byWidget(page1Center)).height, 600.0 - 44.0 - 50.0); expect(tester.getSize(find.byWidget(page1Center)).height, 600.0 - 44.0 - 50.0);
}); });
testWidgets('Contents have automatic sliver padding between translucent bars', (WidgetTester tester) async {
final Container content = new Container(height: 600.0, width: 600.0);
await tester.pumpWidget(
new WidgetsApp(
color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>(
settings: settings,
builder: (BuildContext context) {
return new MediaQuery(
data: const MediaQueryData(
padding: const EdgeInsets.symmetric(vertical: 20.0),
),
child: new CupertinoTabScaffold(
tabBar: 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'),
),
],
),
tabBuilder: (BuildContext context, int index) {
return index == 0
? new CupertinoPageScaffold(
navigationBar: const CupertinoNavigationBar(
middle: const Text('Title'),
),
child: new ListView(
children: <Widget>[
content,
],
),
)
: new Stack();
}
),
);
},
);
},
),
);
// List content automatically padded by nav bar and top media query padding.
expect(tester.getTopLeft(find.byWidget(content)).dy, 20.0 + 44.0);
// Overscroll to the bottom.
await tester.drag(find.byWidget(content), const Offset(0.0, -400.0));
await tester.pump(const Duration(seconds: 1));
// List content automatically padded by tab bar and bottom media query padding.
expect(tester.getBottomLeft(find.byWidget(content)).dy, 600 - 20.0 - 50.0);
});
testWidgets('iOS independent tab navigation', (WidgetTester tester) async { testWidgets('iOS independent tab navigation', (WidgetTester tester) async {
// A full on iOS information architecture app with 2 tabs, and 2 pages // A full on iOS information architecture app with 2 tabs, and 2 pages
// in each with independent navigation states. // in each with independent navigation states.
......
...@@ -265,32 +265,4 @@ void main() { ...@@ -265,32 +265,4 @@ void main() {
expect(delegate.log, equals(<String>['didFinishLayout firstIndex=2 lastIndex=5'])); expect(delegate.log, equals(<String>['didFinishLayout firstIndex=2 lastIndex=5']));
delegate.log.clear(); delegate.log.clear();
}); });
testWidgets('ListView automatically pad MediaQuery on axis', (WidgetTester tester) async {
EdgeInsets innerMediaQueryPadding;
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new MediaQuery(
data: const MediaQueryData(
padding: const EdgeInsets.all(30.0),
),
child: new ListView(
children: <Widget>[
const Text('top', textDirection: TextDirection.ltr),
new Builder(builder: (BuildContext context) {
innerMediaQueryPadding = MediaQuery.of(context).padding;
return new Container();
}),
],
),
),
),
);
// Automatically apply the top/bottom padding into sliver.
expect(tester.getTopLeft(find.text('top')).dy, 30.0);
// Leave left/right padding as is for children.
expect(innerMediaQueryPadding, const EdgeInsets.symmetric(horizontal: 30.0));
});
} }
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