expose scaled fab area in ScaffoldGeometry (#14683)
This commit is contained in:
parent
a11da23852
commit
9bc3bc9822
@ -37,9 +37,6 @@ enum _ScaffoldSlot {
|
||||
statusBar,
|
||||
}
|
||||
|
||||
// Examples can assume:
|
||||
// ScaffoldGeometry scaffoldGeometry;
|
||||
|
||||
/// Geometry information for scaffold components.
|
||||
///
|
||||
/// To get a [ValueNotifier] for the scaffold geometry call
|
||||
@ -49,7 +46,6 @@ class ScaffoldGeometry {
|
||||
const ScaffoldGeometry({
|
||||
this.bottomNavigationBarTop,
|
||||
this.floatingActionButtonArea,
|
||||
this.floatingActionButtonScale: 1.0,
|
||||
});
|
||||
|
||||
/// The distance from the scaffold's top edge to the top edge of the
|
||||
@ -62,38 +58,35 @@ class ScaffoldGeometry {
|
||||
/// The rectangle in which the scaffold is laying out
|
||||
/// [Scaffold.floatingActionButton].
|
||||
///
|
||||
/// The floating action button might be scaled inside this rectangle, to get
|
||||
/// the bounding rectangle in which the floating action is painted scale this
|
||||
/// value by [floatingActionButtonScale].
|
||||
///
|
||||
/// ## Sample code
|
||||
///
|
||||
/// ```dart
|
||||
/// final Rect scaledFab = Rect.lerp(
|
||||
/// scaffoldGeometry.floatingActionButtonArea.center & Size.zero,
|
||||
/// scaffoldGeometry.floatingActionButtonArea,
|
||||
/// scaffoldGeometry.floatingActionButtonScale
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// This is null when there is no floating action button showing.
|
||||
final Rect floatingActionButtonArea;
|
||||
|
||||
/// The amount by which the [Scaffold.floatingActionButton] is scaled.
|
||||
///
|
||||
/// To get the bounding rectangle in which the floating action button is
|
||||
/// painted scaled [floatingActionPosition] by this proportion.
|
||||
///
|
||||
/// This will be 0 when there is no [Scaffold.floatingActionButton] set.
|
||||
final double floatingActionButtonScale;
|
||||
ScaffoldGeometry _scaleFab(double scaleFactor) {
|
||||
if (scaleFactor == 1.0)
|
||||
return this;
|
||||
|
||||
if (scaleFactor == 0.0)
|
||||
return new ScaffoldGeometry(bottomNavigationBarTop: bottomNavigationBarTop);
|
||||
|
||||
final Rect scaledFab = Rect.lerp(
|
||||
floatingActionButtonArea.center & Size.zero,
|
||||
floatingActionButtonArea,
|
||||
scaleFactor
|
||||
);
|
||||
return new ScaffoldGeometry(
|
||||
bottomNavigationBarTop: bottomNavigationBarTop,
|
||||
floatingActionButtonArea: scaledFab,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ScaffoldGeometryNotifier extends ValueNotifier<ScaffoldGeometry> {
|
||||
_ScaffoldGeometryNotifier(ScaffoldGeometry geometry, this.context)
|
||||
: assert (context != null),
|
||||
super(geometry);
|
||||
class _ScaffoldGeometryNotifier extends ChangeNotifier implements ValueListenable<ScaffoldGeometry> {
|
||||
_ScaffoldGeometryNotifier(this.geometry, this.context)
|
||||
: assert (context != null);
|
||||
|
||||
final BuildContext context;
|
||||
double fabScale;
|
||||
ScaffoldGeometry geometry;
|
||||
|
||||
@override
|
||||
ScaffoldGeometry get value {
|
||||
@ -107,7 +100,7 @@ class _ScaffoldGeometryNotifier extends ValueNotifier<ScaffoldGeometry> {
|
||||
);
|
||||
return true;
|
||||
}());
|
||||
return super.value;
|
||||
return geometry._scaleFab(fabScale);
|
||||
}
|
||||
|
||||
void _updateWith({
|
||||
@ -115,16 +108,12 @@ class _ScaffoldGeometryNotifier extends ValueNotifier<ScaffoldGeometry> {
|
||||
Rect floatingActionButtonArea,
|
||||
double floatingActionButtonScale,
|
||||
}) {
|
||||
final double newFloatingActionButtonScale = floatingActionButtonScale ?? super.value?.floatingActionButtonScale;
|
||||
Rect newFloatingActionButtonArea;
|
||||
if (newFloatingActionButtonScale != 0.0)
|
||||
newFloatingActionButtonArea = floatingActionButtonArea ?? super.value?.floatingActionButtonArea;
|
||||
|
||||
value = new ScaffoldGeometry(
|
||||
bottomNavigationBarTop: bottomNavigationBarTop ?? super.value?.bottomNavigationBarTop,
|
||||
floatingActionButtonArea: newFloatingActionButtonArea,
|
||||
floatingActionButtonScale: newFloatingActionButtonScale,
|
||||
fabScale = floatingActionButtonScale ?? fabScale;
|
||||
geometry = new ScaffoldGeometry(
|
||||
bottomNavigationBarTop: bottomNavigationBarTop ?? geometry?.bottomNavigationBarTop,
|
||||
floatingActionButtonArea: floatingActionButtonArea ?? geometry?.floatingActionButtonArea,
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -832,10 +832,6 @@ void main() {
|
||||
geometry.floatingActionButtonArea,
|
||||
fabRect
|
||||
);
|
||||
expect(
|
||||
geometry.floatingActionButtonScale,
|
||||
1.0
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('no floatingActionButton', (WidgetTester tester) async {
|
||||
@ -849,11 +845,6 @@ void main() {
|
||||
final GeometryListenerState listenerState = tester.state(find.byType(GeometryListener));
|
||||
final ScaffoldGeometry geometry = listenerState.cache.value;
|
||||
|
||||
expect(
|
||||
geometry.floatingActionButtonScale,
|
||||
0.0
|
||||
);
|
||||
|
||||
expect(
|
||||
geometry.floatingActionButtonArea,
|
||||
null
|
||||
@ -878,18 +869,77 @@ void main() {
|
||||
),
|
||||
)));
|
||||
|
||||
final GeometryListenerState listenerState = tester.state(find.byType(GeometryListener));
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
|
||||
final GeometryListenerState listenerState = tester.state(find.byType(GeometryListener));
|
||||
final ScaffoldGeometry geometry = listenerState.cache.value;
|
||||
ScaffoldGeometry geometry = listenerState.cache.value;
|
||||
|
||||
final Rect transitioningFabRect = geometry.floatingActionButtonArea;
|
||||
|
||||
await tester.pump(const Duration(seconds: 3));
|
||||
geometry = listenerState.cache.value;
|
||||
final RenderBox floatingActionButtonBox = tester.renderObject(find.byKey(key));
|
||||
final Rect fabRect = floatingActionButtonBox.localToGlobal(Offset.zero) & floatingActionButtonBox.size;
|
||||
|
||||
expect(
|
||||
geometry.floatingActionButtonScale,
|
||||
inExclusiveRange(0.0, 1.0),
|
||||
geometry.floatingActionButtonArea,
|
||||
fabRect
|
||||
);
|
||||
|
||||
expect(
|
||||
geometry.floatingActionButtonArea.center,
|
||||
transitioningFabRect.center
|
||||
);
|
||||
|
||||
expect(
|
||||
geometry.floatingActionButtonArea.width,
|
||||
greaterThan(transitioningFabRect.width)
|
||||
);
|
||||
|
||||
expect(
|
||||
geometry.floatingActionButtonArea.height,
|
||||
greaterThan(transitioningFabRect.height)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('change notifications', (WidgetTester tester) async {
|
||||
final GlobalKey key = new GlobalKey();
|
||||
int numNotificationsAtLastFrame = 0;
|
||||
await tester.pumpWidget(new MaterialApp(home: new Scaffold(
|
||||
body: new ConstrainedBox(
|
||||
constraints: const BoxConstraints.expand(height: 80.0),
|
||||
child: new GeometryListener(),
|
||||
),
|
||||
)));
|
||||
|
||||
final GeometryListenerState listenerState = tester.state(find.byType(GeometryListener));
|
||||
|
||||
expect(listenerState.numNotifications, greaterThan(numNotificationsAtLastFrame));
|
||||
numNotificationsAtLastFrame = listenerState.numNotifications;
|
||||
|
||||
await tester.pumpWidget(new MaterialApp(home: new Scaffold(
|
||||
body: new Container(),
|
||||
floatingActionButton: new FloatingActionButton(
|
||||
key: key,
|
||||
child: new GeometryListener(),
|
||||
onPressed: () {},
|
||||
),
|
||||
)));
|
||||
|
||||
expect(listenerState.numNotifications, greaterThan(numNotificationsAtLastFrame));
|
||||
numNotificationsAtLastFrame = listenerState.numNotifications;
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
|
||||
expect(listenerState.numNotifications, greaterThan(numNotificationsAtLastFrame));
|
||||
numNotificationsAtLastFrame = listenerState.numNotifications;
|
||||
|
||||
await tester.pump(const Duration(seconds: 3));
|
||||
|
||||
expect(listenerState.numNotifications, greaterThan(numNotificationsAtLastFrame));
|
||||
numNotificationsAtLastFrame = listenerState.numNotifications;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class GeometryListener extends StatefulWidget {
|
||||
|
Loading…
x
Reference in New Issue
Block a user