Skip to content

Commit d8b57c2

Browse files
authored
Fix SliverAppBar title opacity and test all cases (flutter#26021)
1 parent 4ad3d99 commit d8b57c2

File tree

3 files changed

+221
-38
lines changed

3 files changed

+221
-38
lines changed

packages/flutter/lib/src/material/app_bar.dart

+16-2
Original file line numberDiff line numberDiff line change
@@ -650,8 +650,22 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
650650
@override
651651
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
652652
final double visibleMainHeight = maxExtent - shrinkOffset - topPadding;
653-
final double toolbarOpacity = pinned ? 1.0
654-
: ((visibleMainHeight - _bottomHeight) / kToolbarHeight).clamp(0.0, 1.0);
653+
654+
// Truth table for `toolbarOpacity`:
655+
// pinned | floating | bottom != null || opacity
656+
// ----------------------------------------------
657+
// 0 | 0 | 0 || fade
658+
// 0 | 0 | 1 || fade
659+
// 0 | 1 | 0 || fade
660+
// 0 | 1 | 1 || fade
661+
// 1 | 0 | 0 || 1.0
662+
// 1 | 0 | 1 || 1.0
663+
// 1 | 1 | 0 || 1.0
664+
// 1 | 1 | 1 || fade
665+
final double toolbarOpacity = !pinned || (floating && bottom != null)
666+
? ((visibleMainHeight - _bottomHeight) / kToolbarHeight).clamp(0.0, 1.0)
667+
: 1.0;
668+
655669
final Widget appBar = FlexibleSpaceBar.createSettings(
656670
minExtent: minExtent,
657671
maxExtent: maxExtent,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
// Copyright 2019 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter/rendering.dart';
6+
import 'package:flutter_test/flutter_test.dart';
7+
import 'package:flutter/material.dart';
8+
9+
void main() {
10+
testWidgets('!pinned && !floating && !bottom ==> fade opactiy', (WidgetTester tester) async {
11+
final ScrollController controller = ScrollController();
12+
await tester.pumpWidget(
13+
_TestWidget(
14+
pinned: false,
15+
floating: false,
16+
bottom: false,
17+
controller: controller,
18+
)
19+
);
20+
21+
final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
22+
expect(render.text.style.color.opacity, 1.0);
23+
24+
controller.jumpTo(200.0);
25+
await tester.pumpAndSettle();
26+
expect(render.text.style.color.opacity, 0.0);
27+
});
28+
29+
testWidgets('!pinned && !floating && bottom ==> fade opactiy', (WidgetTester tester) async {
30+
final ScrollController controller = ScrollController();
31+
await tester.pumpWidget(
32+
_TestWidget(
33+
pinned: false,
34+
floating: false,
35+
bottom: true,
36+
controller: controller,
37+
)
38+
);
39+
40+
final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
41+
expect(render.text.style.color.opacity, 1.0);
42+
43+
controller.jumpTo(200.0);
44+
await tester.pumpAndSettle();
45+
expect(render.text.style.color.opacity, 0.0);
46+
});
47+
48+
testWidgets('!pinned && floating && !bottom ==> fade opactiy', (WidgetTester tester) async {
49+
final ScrollController controller = ScrollController();
50+
await tester.pumpWidget(
51+
_TestWidget(
52+
pinned: false,
53+
floating: true,
54+
bottom: false,
55+
controller: controller,
56+
)
57+
);
58+
59+
final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
60+
expect(render.text.style.color.opacity, 1.0);
61+
62+
controller.jumpTo(200.0);
63+
await tester.pumpAndSettle();
64+
expect(render.text.style.color.opacity, 0.0);
65+
});
66+
67+
testWidgets('!pinned && floating && bottom ==> fade opactiy', (WidgetTester tester) async {
68+
final ScrollController controller = ScrollController();
69+
await tester.pumpWidget(
70+
_TestWidget(
71+
pinned: false,
72+
floating: true,
73+
bottom: true,
74+
controller: controller,
75+
)
76+
);
77+
78+
final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
79+
expect(render.text.style.color.opacity, 1.0);
80+
81+
controller.jumpTo(200.0);
82+
await tester.pumpAndSettle();
83+
expect(render.text.style.color.opacity, 0.0);
84+
});
85+
86+
testWidgets('pinned && !floating && !bottom ==> 1.0 opacity', (WidgetTester tester) async {
87+
final ScrollController controller = ScrollController();
88+
await tester.pumpWidget(
89+
_TestWidget(
90+
pinned: true,
91+
floating: false,
92+
bottom: false,
93+
controller: controller,
94+
)
95+
);
96+
97+
final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
98+
expect(render.text.style.color.opacity, 1.0);
99+
100+
controller.jumpTo(200.0);
101+
await tester.pumpAndSettle();
102+
expect(render.text.style.color.opacity, 1.0);
103+
});
104+
105+
testWidgets('pinned && !floating && bottom ==> 1.0 opacity', (WidgetTester tester) async {
106+
final ScrollController controller = ScrollController();
107+
await tester.pumpWidget(
108+
_TestWidget(
109+
pinned: true,
110+
floating: false,
111+
bottom: true,
112+
controller: controller,
113+
)
114+
);
115+
116+
final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
117+
expect(render.text.style.color.opacity, 1.0);
118+
119+
controller.jumpTo(200.0);
120+
await tester.pumpAndSettle();
121+
expect(render.text.style.color.opacity, 1.0);
122+
});
123+
124+
testWidgets('pinned && floating && !bottom ==> 1.0 opacity', (WidgetTester tester) async {
125+
// Regression test for https://github.com/flutter/flutter/issues/25000.
126+
127+
final ScrollController controller = ScrollController();
128+
await tester.pumpWidget(
129+
_TestWidget(
130+
pinned: true,
131+
floating: true,
132+
bottom: false,
133+
controller: controller,
134+
)
135+
);
136+
137+
final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
138+
expect(render.text.style.color.opacity, 1.0);
139+
140+
controller.jumpTo(200.0);
141+
await tester.pumpAndSettle();
142+
expect(render.text.style.color.opacity, 1.0);
143+
});
144+
145+
testWidgets('pinned && floating && bottom ==> fade opactiy', (WidgetTester tester) async {
146+
// Regression test for https://github.com/flutter/flutter/issues/25993.
147+
148+
final ScrollController controller = ScrollController();
149+
await tester.pumpWidget(
150+
_TestWidget(
151+
pinned: true,
152+
floating: true,
153+
bottom: true,
154+
controller: controller,
155+
)
156+
);
157+
158+
final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
159+
expect(render.text.style.color.opacity, 1.0);
160+
161+
controller.jumpTo(200.0);
162+
await tester.pumpAndSettle();
163+
expect(render.text.style.color.opacity, 0.0);
164+
});
165+
}
166+
167+
class _TestWidget extends StatelessWidget {
168+
169+
const _TestWidget({this.pinned, this.floating, this.bottom, this.controller,});
170+
171+
final bool pinned;
172+
final bool floating;
173+
final bool bottom;
174+
final ScrollController controller;
175+
176+
@override
177+
Widget build(BuildContext context) {
178+
return MaterialApp(
179+
home: CustomScrollView(
180+
controller: controller,
181+
slivers: <Widget>[
182+
SliverAppBar(
183+
pinned: pinned,
184+
floating: floating,
185+
expandedHeight: 120.0,
186+
title: const Text('Hallo Welt!!1'),
187+
bottom: !bottom ? null : PreferredSize(
188+
preferredSize: const Size.fromHeight(35.0),
189+
child: Container(),
190+
),
191+
),
192+
SliverList(
193+
delegate: SliverChildListDelegate(List<Widget>.generate(20, (int i) {
194+
return Container(
195+
child: Text('Tile $i'),
196+
height: 100.0,
197+
);
198+
})),
199+
)
200+
],
201+
),
202+
);
203+
}
204+
205+
}

packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart

-36
Original file line numberDiff line numberDiff line change
@@ -112,40 +112,4 @@ void main() {
112112
expect(render.geometry.paintExtent, availableHeight);
113113
expect(render.geometry.layoutExtent, 0.0);
114114
});
115-
116-
testWidgets('Text does not dissapear when scrolled up', (WidgetTester tester) async {
117-
// Regression test for https://github.com/flutter/flutter/issues/25000.
118-
119-
final ScrollController controller = ScrollController();
120-
await tester.pumpWidget(
121-
MaterialApp(
122-
home: CustomScrollView(
123-
controller: controller,
124-
slivers: <Widget>[
125-
const SliverAppBar(
126-
pinned: true,
127-
floating: true,
128-
expandedHeight: 120.0,
129-
title: Text('Hallo Welt!!1'),
130-
),
131-
SliverList(
132-
delegate: SliverChildListDelegate(List<Widget>.generate(20, (int i) {
133-
return Container(
134-
child: Text('Tile $i'),
135-
height: 100.0,
136-
);
137-
})),
138-
)
139-
],
140-
),
141-
),
142-
);
143-
144-
final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
145-
expect(render.text.style.color.opacity, 1.0);
146-
147-
controller.jumpTo(200.0);
148-
await tester.pumpAndSettle();
149-
expect(render.text.style.color.opacity, 1.0);
150-
});
151115
}

0 commit comments

Comments
 (0)