Commit fa0bcce7 authored by xster's avatar xster Committed by GitHub

Add iOS 11 style large titles to cupertino nav bar (#12002)

* Things lay out but the effects not right yet

* Remaining functionalities and tests

* one line large title only

* Add more docs

* review
parent e830c5eb
......@@ -113,9 +113,10 @@ class _CupertinoScaffoldState extends State<CupertinoScaffold> {
/// Pad the given middle widget with or without top and bottom offsets depending
/// on whether the middle widget should slide behind translucent bars.
Widget _padMiddle(Widget middle) {
double topPadding = MediaQuery.of(context).padding.top;
double topPadding = 0.0;
if (widget.navigationBar is CupertinoNavigationBar) {
final CupertinoNavigationBar top = widget.navigationBar;
topPadding += MediaQuery.of(context).padding.top;
if (top.opaque)
topPadding += top.preferredSize.height;
}
......
......@@ -4,7 +4,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_test/flutter_test.dart' hide TypeMatcher;
int count = 0;
......@@ -14,9 +14,9 @@ void main() {
new WidgetsApp(
color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) {
return new PageRouteBuilder<Null>(
return new CupertinoPageRoute<Null>(
settings: settings,
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
builder: (BuildContext context) {
return const CupertinoNavigationBar(
leading: const CupertinoButton(child: const Text('Something'), onPressed: null,),
middle: const Text('Title'),
......@@ -36,9 +36,9 @@ void main() {
new WidgetsApp(
color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) {
return new PageRouteBuilder<Null>(
return new CupertinoPageRoute<Null>(
settings: settings,
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
builder: (BuildContext context) {
return const CupertinoNavigationBar(
middle: const Text('Title'),
backgroundColor: const Color(0xFFE5E5E5),
......@@ -56,9 +56,9 @@ void main() {
new WidgetsApp(
color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) {
return new PageRouteBuilder<Null>(
return new CupertinoPageRoute<Null>(
settings: settings,
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
builder: (BuildContext context) {
return const CupertinoNavigationBar(
middle: const Text('Title'),
);
......@@ -76,9 +76,9 @@ void main() {
new WidgetsApp(
color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) {
return new PageRouteBuilder<Null>(
return new CupertinoPageRoute<Null>(
settings: settings,
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
builder: (BuildContext context) {
return const CupertinoNavigationBar(
leading: const _ExpectStyles(color: const Color(0xFF001122), index: 0x000001),
middle: const _ExpectStyles(color: const Color(0xFF000000), index: 0x000100),
......@@ -92,6 +92,118 @@ void main() {
);
expect(count, 0x010101);
});
testWidgets('No slivers with no large titles', (WidgetTester tester) async {
await tester.pumpWidget(
new WidgetsApp(
color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>(
settings: settings,
builder: (BuildContext context) {
return const CupertinoScaffold(
navigationBar: const CupertinoNavigationBar(
middle: const Text('Title'),
),
child: const Center(),
);
},
);
},
),
);
expect(find.byType(SliverPersistentHeader), findsNothing);
});
testWidgets('Large title nav bar scrolls', (WidgetTester tester) async {
final ScrollController scrollController = new ScrollController();
await tester.pumpWidget(
new WidgetsApp(
color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>(
settings: settings,
builder: (BuildContext context) {
return new CupertinoScaffold(
child: new CustomScrollView(
controller: scrollController,
slivers: <Widget>[
const CupertinoNavigationBar(
middle: const Text('Title'),
largeTitle: true,
),
new SliverToBoxAdapter(
child: new Container(
height: 1200.0,
),
),
],
),
);
},
);
},
),
);
expect(scrollController.offset, 0.0);
expect(tester.getTopLeft(find.byType(NavigationToolbar)).dy, 0.0);
expect(tester.getSize(find.byType(NavigationToolbar)).height, 44.0);
expect(find.text('Title'), findsNWidgets(2)); // Though only one is visible.
List<Element> titles = tester.elementList(find.text('Title'))
.toList()
..sort((Element a, Element b) {
final RenderParagraph aParagraph = a.renderObject;
final RenderParagraph bParagraph = b.renderObject;
return aParagraph.text.style.fontSize.compareTo(bParagraph.text.style.fontSize);
});
Iterable<double> opacities = titles.map((Element element) {
final RenderOpacity renderOpacity = element.ancestorRenderObjectOfType(const TypeMatcher<RenderOpacity>());
return renderOpacity.opacity;
});
expect(opacities, <double> [
0.0, // Initially the smaller font title is invisible.
1.0, // The larger font title is visible.
]);
expect(tester.getTopLeft(find.widgetWithText(OverflowBox, 'Title')).dy, 44.0);
expect(tester.getSize(find.widgetWithText(OverflowBox, 'Title')).height, 56.0);
scrollController.jumpTo(600.0);
await tester.pump(); // Once to trigger the opacity animation.
await tester.pump(const Duration(milliseconds: 300));
titles = tester.elementList(find.text('Title'))
.toList()
..sort((Element a, Element b) {
final RenderParagraph aParagraph = a.renderObject;
final RenderParagraph bParagraph = b.renderObject;
return aParagraph.text.style.fontSize.compareTo(bParagraph.text.style.fontSize);
});
opacities = titles.map((Element element) {
final RenderOpacity renderOpacity = element.ancestorRenderObjectOfType(const TypeMatcher<RenderOpacity>());
return renderOpacity.opacity;
});
expect(opacities, <double> [
1.0, // Smaller font title now visiblee
0.0, // Larger font title invisible.
]);
// The persistent toolbar doesn't move or change size.
expect(tester.getTopLeft(find.byType(NavigationToolbar)).dy, 0.0);
expect(tester.getSize(find.byType(NavigationToolbar)).height, 44.0);
expect(tester.getTopLeft(find.widgetWithText(OverflowBox, 'Title')).dy, 44.0);
// The OverflowBox is squished with the text in it.
expect(tester.getSize(find.widgetWithText(OverflowBox, 'Title')).height, 0.0);
});
}
class _ExpectStyles extends StatelessWidget {
......
......@@ -20,10 +20,9 @@ void main() {
new WidgetsApp(
color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) {
// TODO(xster): change to a CupertinoPageRoute.
return new PageRouteBuilder<Null>(
return new CupertinoPageRoute<Null>(
settings: settings,
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
builder: (BuildContext context) {
return const CupertinoScaffold(
// Default nav bar is translucent.
navigationBar: const CupertinoNavigationBar(
......@@ -47,10 +46,9 @@ void main() {
new WidgetsApp(
color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) {
// TODO(xster): change to a CupertinoPageRoute.
return new PageRouteBuilder<Null>(
return new CupertinoPageRoute<Null>(
settings: settings,
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
builder: (BuildContext context) {
return new CupertinoScaffold.tabbed(
navigationBar: const CupertinoNavigationBar(
backgroundColor: CupertinoColors.white,
......@@ -77,10 +75,9 @@ void main() {
new WidgetsApp(
color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) {
// TODO(xster): change to a CupertinoPageRoute.
return new PageRouteBuilder<Null>(
return new CupertinoPageRoute<Null>(
settings: settings,
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
builder: (BuildContext context) {
return new CupertinoScaffold.tabbed(
navigationBar: const CupertinoNavigationBar(
backgroundColor: CupertinoColors.white,
......@@ -142,10 +139,9 @@ void main() {
new WidgetsApp(
color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) {
// TODO(xster): change to a CupertinoPageRoute.
return new PageRouteBuilder<Null>(
return new CupertinoPageRoute<Null>(
settings: settings,
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
builder: (BuildContext context) {
return new CupertinoScaffold.tabbed(
navigationBar: const CupertinoNavigationBar(
backgroundColor: CupertinoColors.white,
......
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