Unverified Commit 9bc3bc98 authored by amirh's avatar amirh Committed by GitHub

expose scaled fab area in ScaffoldGeometry (#14683)

parent a11da238
......@@ -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.floatingActionButtonArea,
fabRect
);
expect(
geometry.floatingActionButtonScale,
inExclusiveRange(0.0, 1.0),
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 {
......
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