Enable extended FAB hero transition resizing (#19534)
This commit is contained in:
parent
6016882a56
commit
a960b870cc
@ -2,7 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/painting.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'button.dart';
|
||||
@ -103,15 +106,17 @@ class FloatingActionButton extends StatefulWidget {
|
||||
assert(isExtended != null),
|
||||
_sizeConstraints = _kExtendedSizeConstraints,
|
||||
mini = false,
|
||||
child = new Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
const SizedBox(width: 16.0),
|
||||
icon,
|
||||
const SizedBox(width: 8.0),
|
||||
label,
|
||||
const SizedBox(width: 20.0),
|
||||
],
|
||||
child = new _ChildOverflowBox(
|
||||
child: new Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
const SizedBox(width: 16.0),
|
||||
icon,
|
||||
const SizedBox(width: 8.0),
|
||||
label,
|
||||
const SizedBox(width: 20.0),
|
||||
],
|
||||
),
|
||||
),
|
||||
super(key: key);
|
||||
|
||||
@ -273,3 +278,55 @@ class _FloatingActionButtonState extends State<FloatingActionButton> {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// This widget's size matches its child's size unless its constraints
|
||||
// force it to be larger or smaller. The child is centered.
|
||||
//
|
||||
// Used to encapsulate extended FABs whose size is fixed, using Row
|
||||
// and MainAxisSize.min, to be as wide as their label and icon.
|
||||
class _ChildOverflowBox extends SingleChildRenderObjectWidget {
|
||||
const _ChildOverflowBox({
|
||||
Key key,
|
||||
Widget child,
|
||||
}) : super(key: key, child: child);
|
||||
|
||||
@override
|
||||
_RenderChildOverflowBox createRenderObject(BuildContext context) {
|
||||
return new _RenderChildOverflowBox(
|
||||
textDirection: Directionality.of(context),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void updateRenderObject(BuildContext context, _RenderChildOverflowBox renderObject) {
|
||||
renderObject
|
||||
..textDirection = Directionality.of(context);
|
||||
}
|
||||
}
|
||||
|
||||
class _RenderChildOverflowBox extends RenderAligningShiftedBox {
|
||||
_RenderChildOverflowBox({
|
||||
RenderBox child,
|
||||
TextDirection textDirection,
|
||||
}) : super(child: child, alignment: Alignment.center, textDirection: textDirection);
|
||||
|
||||
@override
|
||||
double computeMinIntrinsicWidth(double height) => 0.0;
|
||||
|
||||
@override
|
||||
double computeMinIntrinsicHeight(double width) => 0.0;
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
if (child != null) {
|
||||
child.layout(const BoxConstraints(), parentUsesSize: true);
|
||||
size = new Size(
|
||||
math.max(constraints.minWidth, math.min(constraints.maxWidth, child.size.width)),
|
||||
math.max(constraints.minHeight, math.min(constraints.maxHeight, child.size.height)),
|
||||
);
|
||||
alignChild();
|
||||
} else {
|
||||
size = constraints.biggest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -344,5 +344,68 @@ void main() {
|
||||
semantics.dispose();
|
||||
});
|
||||
|
||||
testWidgets('extended FAB hero transitions succeed', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/18782
|
||||
|
||||
await tester.pumpWidget(
|
||||
new MaterialApp(
|
||||
home: new Scaffold(
|
||||
floatingActionButton: new Builder(
|
||||
builder: (BuildContext context) { // define context of Navigator.push()
|
||||
return new FloatingActionButton.extended(
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text('A long FAB label'),
|
||||
onPressed: () {
|
||||
Navigator.push(context, new MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) {
|
||||
return new Scaffold(
|
||||
floatingActionButton: new FloatingActionButton.extended(
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text('X'),
|
||||
onPressed: () { },
|
||||
),
|
||||
body: new Center(
|
||||
child: new RaisedButton(
|
||||
child: const Text('POP'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
));
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
body: const Center(
|
||||
child: const Text('Hello World'),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Finder longFAB = find.text('A long FAB label');
|
||||
final Finder shortFAB = find.text('X');
|
||||
final Finder helloWorld = find.text('Hello World');
|
||||
|
||||
expect(longFAB, findsOneWidget);
|
||||
expect(shortFAB, findsNothing);
|
||||
expect(helloWorld, findsOneWidget);
|
||||
|
||||
await tester.tap(longFAB);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(shortFAB, findsOneWidget);
|
||||
expect(longFAB, findsNothing);
|
||||
|
||||
// Trigger a hero transition from shortFAB to longFAB.
|
||||
await tester.tap(find.text('POP'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(longFAB, findsOneWidget);
|
||||
expect(shortFAB, findsNothing);
|
||||
expect(helloWorld, findsOneWidget);
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user