Support RTL Cupertino nav bar transitions between routes (#23221)
This commit is contained in:
parent
125b5d623c
commit
d00a549f2d
@ -1410,8 +1410,8 @@ class _TransitionableNavigationBar extends StatelessWidget {
|
||||
class _NavigationBarTransition extends StatelessWidget {
|
||||
_NavigationBarTransition({
|
||||
@required this.animation,
|
||||
@required _TransitionableNavigationBar topNavBar,
|
||||
@required _TransitionableNavigationBar bottomNavBar,
|
||||
@required this.topNavBar,
|
||||
@required this.bottomNavBar,
|
||||
}) : heightTween = Tween<double>(
|
||||
begin: bottomNavBar.renderBox.size.height,
|
||||
end: topNavBar.renderBox.size.height,
|
||||
@ -1423,15 +1423,11 @@ class _NavigationBarTransition extends StatelessWidget {
|
||||
borderTween = BorderTween(
|
||||
begin: bottomNavBar.border,
|
||||
end: topNavBar.border,
|
||||
),
|
||||
componentsTransition = _NavigationBarComponentsTransition(
|
||||
animation: animation,
|
||||
bottomNavBar: bottomNavBar,
|
||||
topNavBar: topNavBar,
|
||||
);
|
||||
|
||||
final Animation<double> animation;
|
||||
final _NavigationBarComponentsTransition componentsTransition;
|
||||
final _TransitionableNavigationBar topNavBar;
|
||||
final _TransitionableNavigationBar bottomNavBar;
|
||||
|
||||
final Tween<double> heightTween;
|
||||
final ColorTween backgroundTween;
|
||||
@ -1439,6 +1435,13 @@ class _NavigationBarTransition extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final _NavigationBarComponentsTransition componentsTransition = _NavigationBarComponentsTransition(
|
||||
animation: animation,
|
||||
bottomNavBar: bottomNavBar,
|
||||
topNavBar: topNavBar,
|
||||
directionality: Directionality.of(context),
|
||||
);
|
||||
|
||||
final List<Widget> children = <Widget>[
|
||||
// Draw an empty navigation bar box with changing shape behind all the
|
||||
// moving components without any components inside it itself.
|
||||
@ -1516,6 +1519,7 @@ class _NavigationBarComponentsTransition {
|
||||
@required this.animation,
|
||||
@required _TransitionableNavigationBar bottomNavBar,
|
||||
@required _TransitionableNavigationBar topNavBar,
|
||||
@required TextDirection directionality,
|
||||
}) : bottomComponents = bottomNavBar.componentsKeys,
|
||||
topComponents = topNavBar.componentsKeys,
|
||||
bottomNavBarBox = bottomNavBar.renderBox,
|
||||
@ -1528,7 +1532,8 @@ class _NavigationBarComponentsTransition {
|
||||
topLargeExpanded = topNavBar.largeExpanded,
|
||||
transitionBox =
|
||||
// paintBounds are based on offset zero so it's ok to expand the Rects.
|
||||
bottomNavBar.renderBox.paintBounds.expandToInclude(topNavBar.renderBox.paintBounds);
|
||||
bottomNavBar.renderBox.paintBounds.expandToInclude(topNavBar.renderBox.paintBounds),
|
||||
forwardDirection = directionality == TextDirection.ltr ? 1.0 : -1.0;
|
||||
|
||||
static final Animatable<double> fadeOut = Tween<double>(
|
||||
begin: 1.0,
|
||||
@ -1560,6 +1565,9 @@ class _NavigationBarComponentsTransition {
|
||||
// sizing component of RelativeRects will be based on this rect's size.
|
||||
final Rect transitionBox;
|
||||
|
||||
// x-axis unity number representing the direction of growth for text.
|
||||
final double forwardDirection;
|
||||
|
||||
// Take a widget it its original ancestor navigation bar render box and
|
||||
// translate it into a RelativeBox in the transition navigation bar box.
|
||||
RelativeRect positionInTransitionBox(
|
||||
@ -1579,8 +1587,8 @@ class _NavigationBarComponentsTransition {
|
||||
// ancestor navigation bar to another widget's position in that widget's
|
||||
// navigation bar.
|
||||
//
|
||||
// Anchor their positions based on the center of their respective render
|
||||
// boxes' leading edge.
|
||||
// Anchor their positions based on the vertical middle of their respective
|
||||
// render boxes' leading edge.
|
||||
//
|
||||
// Also produce RelativeRects with sizes that would preserve the constant
|
||||
// BoxConstraints of the 'from' widget so that animating font sizes etc don't
|
||||
@ -1595,7 +1603,11 @@ class _NavigationBarComponentsTransition {
|
||||
|
||||
final RenderBox fromBox = fromKey.currentContext.findRenderObject();
|
||||
final RenderBox toBox = toKey.currentContext.findRenderObject();
|
||||
final Rect toRect =
|
||||
|
||||
// We move a box with the size of the 'from' render object such that its
|
||||
// upper left corner is at the upper left corner of the 'to' render object.
|
||||
// With slight y axis adjustment for those render objects' height differences.
|
||||
Rect toRect =
|
||||
toBox.localToGlobal(
|
||||
Offset.zero,
|
||||
ancestor: toNavBarBox,
|
||||
@ -1604,6 +1616,12 @@ class _NavigationBarComponentsTransition {
|
||||
- fromBox.size.height / 2 + toBox.size.height / 2
|
||||
) & fromBox.size; // Keep the from render object's size.
|
||||
|
||||
if (forwardDirection < 0) {
|
||||
// If RTL, move the center right to the center right instead of matching
|
||||
// the center lefts.
|
||||
toRect = toRect.translate(- fromBox.size.width + toBox.size.width, 0.0);
|
||||
}
|
||||
|
||||
return RelativeRectTween(
|
||||
begin: fromRect,
|
||||
end: RelativeRect.fromRect(toRect, transitionBox),
|
||||
@ -1666,10 +1684,15 @@ class _NavigationBarComponentsTransition {
|
||||
|
||||
final RelativeRect from = positionInTransitionBox(bottomComponents.backLabelKey, from: bottomNavBarBox);
|
||||
|
||||
// Transition away by sliding horizontally to the left off of the screen.
|
||||
// Transition away by sliding horizontally to the leading edge off of the screen.
|
||||
final RelativeRectTween positionTween = RelativeRectTween(
|
||||
begin: from,
|
||||
end: from.shift(Offset(-bottomNavBarBox.size.width / 2.0, 0.0)),
|
||||
end: from.shift(
|
||||
Offset(
|
||||
forwardDirection * (-bottomNavBarBox.size.width / 2.0),
|
||||
0.0,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return PositionedTransition(
|
||||
@ -1696,6 +1719,7 @@ class _NavigationBarComponentsTransition {
|
||||
}
|
||||
|
||||
if (bottomMiddle != null && topBackLabel != null) {
|
||||
// Move from current position to the top page's back label position.
|
||||
return PositionedTransition(
|
||||
rect: animation.drive(slideFromLeadingEdge(
|
||||
fromKey: bottomComponents.middleKey,
|
||||
@ -1722,8 +1746,9 @@ class _NavigationBarComponentsTransition {
|
||||
);
|
||||
}
|
||||
|
||||
// When the top page has a leading widget override, don't move the bottom
|
||||
// middle widget.
|
||||
// When the top page has a leading widget override (one of the few ways to
|
||||
// not have a top back label), don't move the bottom middle widget and just
|
||||
// fade.
|
||||
if (bottomMiddle != null && topLeading != null) {
|
||||
return Positioned.fromRelativeRect(
|
||||
rect: positionInTransitionBox(bottomComponents.middleKey, from: bottomNavBarBox),
|
||||
@ -1751,6 +1776,7 @@ class _NavigationBarComponentsTransition {
|
||||
}
|
||||
|
||||
if (bottomLargeTitle != null && topBackLabel != null) {
|
||||
// Move from current position to the top page's back label position.
|
||||
return PositionedTransition(
|
||||
rect: animation.drive(slideFromLeadingEdge(
|
||||
fromKey: bottomComponents.largeTitleKey,
|
||||
@ -1779,15 +1805,22 @@ class _NavigationBarComponentsTransition {
|
||||
}
|
||||
|
||||
if (bottomLargeTitle != null && topLeading != null) {
|
||||
// Unlike bottom middle, the bottom large title moves when it can't
|
||||
// transition to the top back label position.
|
||||
final RelativeRect from = positionInTransitionBox(bottomComponents.largeTitleKey, from: bottomNavBarBox);
|
||||
|
||||
final RelativeRectTween positionTween = RelativeRectTween(
|
||||
begin: from,
|
||||
end: from.shift(Offset(bottomNavBarBox.size.width / 4.0, 0.0)),
|
||||
end: from.shift(
|
||||
Offset(
|
||||
forwardDirection * bottomNavBarBox.size.width / 4.0,
|
||||
0.0,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Just shift slightly towards the right instead of moving to the back
|
||||
// label position.
|
||||
// Just shift slightly towards the trailing edge instead of moving to the
|
||||
// back label position.
|
||||
return PositionedTransition(
|
||||
rect: animation.drive(positionTween),
|
||||
child: FadeTransition(
|
||||
@ -1851,7 +1884,12 @@ class _NavigationBarComponentsTransition {
|
||||
// right.
|
||||
if (bottomBackChevron == null) {
|
||||
final RenderBox topBackChevronBox = topComponents.backChevronKey.currentContext.findRenderObject();
|
||||
from = to.shift(Offset(topBackChevronBox.size.width * 2.0, 0.0));
|
||||
from = to.shift(
|
||||
Offset(
|
||||
forwardDirection * topBackChevronBox.size.width * 2.0,
|
||||
0.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final RelativeRectTween positionTween = RelativeRectTween(
|
||||
@ -1967,7 +2005,12 @@ class _NavigationBarComponentsTransition {
|
||||
|
||||
// Shift in from the trailing edge of the screen.
|
||||
final RelativeRectTween positionTween = RelativeRectTween(
|
||||
begin: to.shift(Offset(topNavBarBox.size.width / 2.0, 0.0)),
|
||||
begin: to.shift(
|
||||
Offset(
|
||||
forwardDirection * topNavBarBox.size.width / 2.0,
|
||||
0.0,
|
||||
),
|
||||
),
|
||||
end: to,
|
||||
);
|
||||
|
||||
@ -2010,7 +2053,12 @@ class _NavigationBarComponentsTransition {
|
||||
|
||||
// Shift in from the trailing edge of the screen.
|
||||
final RelativeRectTween positionTween = RelativeRectTween(
|
||||
begin: to.shift(Offset(topNavBarBox.size.width, 0.0)),
|
||||
begin: to.shift(
|
||||
Offset(
|
||||
forwardDirection * topNavBarBox.size.width,
|
||||
0.0,
|
||||
),
|
||||
),
|
||||
end: to,
|
||||
);
|
||||
|
||||
|
@ -12,10 +12,17 @@ Future<void> startTransitionBetween(
|
||||
Widget to,
|
||||
String fromTitle,
|
||||
String toTitle,
|
||||
TextDirection textDirection = TextDirection.ltr,
|
||||
}) async {
|
||||
await tester.pumpWidget(
|
||||
const CupertinoApp(
|
||||
home: Placeholder(),
|
||||
CupertinoApp(
|
||||
builder: (BuildContext context, Widget navigator) {
|
||||
return Directionality(
|
||||
textDirection: textDirection,
|
||||
child: navigator,
|
||||
);
|
||||
},
|
||||
home: const Placeholder(),
|
||||
),
|
||||
);
|
||||
|
||||
@ -145,6 +152,29 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Bottom middle moves between middle and back label RTL',
|
||||
(WidgetTester tester) async {
|
||||
await startTransitionBetween(
|
||||
tester,
|
||||
fromTitle: 'Page 1',
|
||||
textDirection: TextDirection.rtl,
|
||||
);
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
|
||||
expect(flying(tester, find.text('Page 1')), findsNWidgets(2));
|
||||
|
||||
// Same as LTR but more to the right now.
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('Page 1')).first),
|
||||
const Offset(366.9275064468384, 13.5),
|
||||
);
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('Page 1')).last),
|
||||
const Offset(366.9275064468384, 13.5),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Bottom middle and top back label transitions their font',
|
||||
(WidgetTester tester) async {
|
||||
await startTransitionBetween(tester, fromTitle: 'Page 1');
|
||||
@ -293,6 +323,52 @@ void main() {
|
||||
checkColorAndPositionAt50ms();
|
||||
});
|
||||
|
||||
testWidgets('Popping mid-transition is symmetrical RTL',
|
||||
(WidgetTester tester) async {
|
||||
await startTransitionBetween(
|
||||
tester,
|
||||
fromTitle: 'Page 1',
|
||||
textDirection: TextDirection.rtl,
|
||||
);
|
||||
|
||||
// Be mid-transition.
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
|
||||
void checkColorAndPositionAt50ms() {
|
||||
// The transition's stack is ordered. The bottom middle is inserted first.
|
||||
final RenderParagraph bottomMiddle =
|
||||
tester.renderObject(flying(tester, find.text('Page 1')).first);
|
||||
expect(bottomMiddle.text.style.color, const Color(0xFF00070F));
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('Page 1')).first),
|
||||
const Offset(366.9275064468384, 13.5),
|
||||
);
|
||||
|
||||
// The top back label is styled exactly the same way. But the opacity tweens
|
||||
// are flipped.
|
||||
final RenderParagraph topBackLabel =
|
||||
tester.renderObject(flying(tester, find.text('Page 1')).last);
|
||||
expect(topBackLabel.text.style.color, const Color(0xFF00070F));
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('Page 1')).last),
|
||||
const Offset(366.9275064468384, 13.5),
|
||||
);
|
||||
}
|
||||
|
||||
checkColorAndPositionAt50ms();
|
||||
|
||||
// Advance more.
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
|
||||
// Pop and reverse the same amount of time.
|
||||
tester.state<NavigatorState>(find.byType(Navigator)).pop();
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
|
||||
// Check that everything's the same as on the way in.
|
||||
checkColorAndPositionAt50ms();
|
||||
});
|
||||
|
||||
testWidgets('There should be no global keys in the hero flight',
|
||||
(WidgetTester tester) async {
|
||||
await startTransitionBetween(tester, fromTitle: 'Page 1');
|
||||
@ -430,6 +506,54 @@ void main() {
|
||||
tester.getTopLeft(backChevron), const Offset(18.033634185791016, 5.0));
|
||||
});
|
||||
|
||||
testWidgets('First appearance of back chevron fades in from the left in RTL',
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
CupertinoApp(
|
||||
builder: (BuildContext context, Widget navigator) {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.rtl,
|
||||
child: navigator,
|
||||
);
|
||||
},
|
||||
home: scaffoldForNavBar(null),
|
||||
),
|
||||
);
|
||||
|
||||
tester
|
||||
.state<NavigatorState>(find.byType(Navigator))
|
||||
.push(CupertinoPageRoute<void>(
|
||||
title: 'Page 1',
|
||||
builder: (BuildContext context) => scaffoldForNavBar(null),
|
||||
));
|
||||
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
|
||||
final Finder backChevron = flying(tester,
|
||||
find.text(String.fromCharCode(CupertinoIcons.back.codePoint)));
|
||||
|
||||
expect(
|
||||
backChevron,
|
||||
// Only one exists from the top page. The bottom page has no back chevron.
|
||||
findsOneWidget,
|
||||
);
|
||||
|
||||
// Come in from the right and fade in.
|
||||
checkOpacity(tester, backChevron, 0.0);
|
||||
expect(
|
||||
tester.getTopRight(backChevron),
|
||||
const Offset(694.0500679016113, 5.0),
|
||||
);
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 150));
|
||||
checkOpacity(tester, backChevron, 0.32467134296894073);
|
||||
expect(
|
||||
tester.getTopRight(backChevron),
|
||||
const Offset(747.966365814209, 5.0),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Back chevron fades out and in when both pages have it',
|
||||
(WidgetTester tester) async {
|
||||
await startTransitionBetween(tester, fromTitle: 'Page 1');
|
||||
@ -474,8 +598,7 @@ void main() {
|
||||
// There's just 1 in flight because there's no back label on the top page.
|
||||
expect(flying(tester, find.text('Page 1')), findsOneWidget);
|
||||
|
||||
checkOpacity(
|
||||
tester, flying(tester, find.text('Page 1')), 0.8609542846679688);
|
||||
checkOpacity(tester, flying(tester, find.text('Page 1')), 0.8609542846679688);
|
||||
|
||||
// The middle widget doesn't move.
|
||||
expect(
|
||||
@ -503,8 +626,7 @@ void main() {
|
||||
|
||||
expect(flying(tester, find.text('custom')), findsOneWidget);
|
||||
|
||||
checkOpacity(
|
||||
tester, flying(tester, find.text('custom')), 0.7655444294214249);
|
||||
checkOpacity(tester, flying(tester, find.text('custom')), 0.7655444294214249);
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('custom'))),
|
||||
const Offset(16.0, 0.0),
|
||||
@ -530,8 +652,7 @@ void main() {
|
||||
|
||||
expect(flying(tester, find.text('custom')), findsOneWidget);
|
||||
|
||||
checkOpacity(
|
||||
tester, flying(tester, find.text('custom')), 0.8393326997756958);
|
||||
checkOpacity(tester, flying(tester, find.text('custom')), 0.8393326997756958);
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('custom'))),
|
||||
const Offset(683.0, 13.5),
|
||||
@ -568,8 +689,7 @@ void main() {
|
||||
expect(flying(tester, find.text('Page 1')), findsOneWidget);
|
||||
|
||||
// Back label fades out faster.
|
||||
checkOpacity(
|
||||
tester, flying(tester, find.text('Page 1')), 0.5584745407104492);
|
||||
checkOpacity(tester, flying(tester, find.text('Page 1')), 0.5584745407104492);
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('Page 1'))),
|
||||
const Offset(24.176071166992188, 13.5),
|
||||
@ -583,6 +703,45 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Bottom back label fades and slides to the right in RTL',
|
||||
(WidgetTester tester) async {
|
||||
await startTransitionBetween(
|
||||
tester,
|
||||
fromTitle: 'Page 1',
|
||||
toTitle: 'Page 2',
|
||||
textDirection: TextDirection.rtl,
|
||||
);
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 500));
|
||||
tester
|
||||
.state<NavigatorState>(find.byType(Navigator))
|
||||
.push(CupertinoPageRoute<void>(
|
||||
title: 'Page 3',
|
||||
builder: (BuildContext context) => scaffoldForNavBar(null),
|
||||
));
|
||||
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
|
||||
// 'Page 1' appears once on Page 2 as the back label.
|
||||
expect(flying(tester, find.text('Page 1')), findsOneWidget);
|
||||
|
||||
// Back label fades out faster.
|
||||
checkOpacity(tester, flying(tester, find.text('Page 1')), 0.5584745407104492);
|
||||
expect(
|
||||
tester.getTopRight(flying(tester, find.text('Page 1'))),
|
||||
const Offset(775.8239288330078, 13.5),
|
||||
);
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 150));
|
||||
checkOpacity(tester, flying(tester, find.text('Page 1')), 0.0);
|
||||
expect(
|
||||
tester.getTopRight(flying(tester, find.text('Page 1'))),
|
||||
// >1000. It's now off the screen.
|
||||
const Offset(1092.9786224365234, 13.5),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Bottom large title moves to top back label',
|
||||
(WidgetTester tester) async {
|
||||
await startTransitionBetween(
|
||||
@ -598,8 +757,7 @@ void main() {
|
||||
// bottom back label fading in.
|
||||
expect(flying(tester, find.text('Page 1')), findsNWidgets(2));
|
||||
|
||||
checkOpacity(
|
||||
tester, flying(tester, find.text('Page 1')).first, 0.8393326997756958);
|
||||
checkOpacity(tester, flying(tester, find.text('Page 1')).first, 0.8393326997756958);
|
||||
checkOpacity(tester, flying(tester, find.text('Page 1')).last, 0.0);
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('Page 1')).first),
|
||||
@ -612,8 +770,7 @@ void main() {
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 150));
|
||||
checkOpacity(tester, flying(tester, find.text('Page 1')).first, 0.0);
|
||||
checkOpacity(
|
||||
tester, flying(tester, find.text('Page 1')).last, 0.6276369094848633);
|
||||
checkOpacity(tester, flying(tester, find.text('Page 1')).last, 0.6276369094848633);
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('Page 1')).first),
|
||||
const Offset(43.278289794921875, 19.23011875152588),
|
||||
@ -653,8 +810,7 @@ void main() {
|
||||
);
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 150));
|
||||
checkOpacity(
|
||||
tester, flying(tester, find.text('A title too long to fit')), 0.0);
|
||||
checkOpacity(tester, flying(tester, find.text('A title too long to fit')), 0.0);
|
||||
checkOpacity(tester, flying(tester, find.text('Back')), 0.6276369094848633);
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('A title too long to fit'))),
|
||||
@ -717,8 +873,7 @@ void main() {
|
||||
|
||||
expect(flying(tester, find.text('Page 2')), findsOneWidget);
|
||||
|
||||
checkOpacity(
|
||||
tester, flying(tester, find.text('Page 2')), 0.0);
|
||||
checkOpacity(tester, flying(tester, find.text('Page 2')), 0.0);
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('Page 2'))),
|
||||
const Offset(725.1760711669922, 13.5),
|
||||
@ -726,14 +881,40 @@ void main() {
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 150));
|
||||
|
||||
checkOpacity(
|
||||
tester, flying(tester, find.text('Page 2')), 0.6972532719373703);
|
||||
checkOpacity(tester, flying(tester, find.text('Page 2')), 0.6972532719373703);
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('Page 2'))),
|
||||
const Offset(408.02137756347656, 13.5),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Top middle fades in and slides in from the left in RTL',
|
||||
(WidgetTester tester) async {
|
||||
await startTransitionBetween(
|
||||
tester,
|
||||
toTitle: 'Page 2',
|
||||
textDirection: TextDirection.rtl,
|
||||
);
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
|
||||
expect(flying(tester, find.text('Page 2')), findsOneWidget);
|
||||
|
||||
checkOpacity(tester, flying(tester, find.text('Page 2')), 0.0);
|
||||
expect(
|
||||
tester.getTopRight(flying(tester, find.text('Page 2'))),
|
||||
const Offset(74.82392883300781, 13.5),
|
||||
);
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 150));
|
||||
|
||||
checkOpacity(tester, flying(tester, find.text('Page 2')), 0.6972532719373703);
|
||||
expect(
|
||||
tester.getTopRight(flying(tester, find.text('Page 2'))),
|
||||
const Offset(391.97862243652344, 13.5),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Top large title fades in and slides in from the right',
|
||||
(WidgetTester tester) async {
|
||||
await startTransitionBetween(
|
||||
@ -746,8 +927,7 @@ void main() {
|
||||
|
||||
expect(flying(tester, find.text('Page 2')), findsOneWidget);
|
||||
|
||||
checkOpacity(
|
||||
tester, flying(tester, find.text('Page 2')), 0.0);
|
||||
checkOpacity(tester, flying(tester, find.text('Page 2')), 0.0);
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('Page 2'))),
|
||||
const Offset(768.3521423339844, 54.0),
|
||||
@ -755,14 +935,41 @@ void main() {
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 150));
|
||||
|
||||
checkOpacity(
|
||||
tester, flying(tester, find.text('Page 2')), 0.6753286570310593);
|
||||
checkOpacity(tester, flying(tester, find.text('Page 2')), 0.6753286570310593);
|
||||
expect(
|
||||
tester.getTopLeft(flying(tester, find.text('Page 2'))),
|
||||
const Offset(134.04275512695312, 54.0),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Top large title fades in and slides in from the left in RTL',
|
||||
(WidgetTester tester) async {
|
||||
await startTransitionBetween(
|
||||
tester,
|
||||
to: const CupertinoSliverNavigationBar(),
|
||||
toTitle: 'Page 2',
|
||||
textDirection: TextDirection.rtl,
|
||||
);
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
|
||||
expect(flying(tester, find.text('Page 2')), findsOneWidget);
|
||||
|
||||
checkOpacity(tester, flying(tester, find.text('Page 2')), 0.0);
|
||||
expect(
|
||||
tester.getTopRight(flying(tester, find.text('Page 2'))),
|
||||
const Offset(31.647857666015625, 54.0),
|
||||
);
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 150));
|
||||
|
||||
checkOpacity(tester, flying(tester, find.text('Page 2')), 0.6753286570310593);
|
||||
expect(
|
||||
tester.getTopRight(flying(tester, find.text('Page 2'))),
|
||||
const Offset(665.9572448730469, 54.0),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Components are not unnecessarily rebuilt during transitions',
|
||||
(WidgetTester tester) async {
|
||||
int bottomBuildTimes = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user