Support notched BottomAppbar when Scaffold.bottomNavigationBar == null (#81228)
This commit is contained in:
parent
3533321b1a
commit
3df0f931fa
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'bottom_app_bar_theme.dart';
|
||||
@ -271,6 +272,7 @@ class BottomAppBar extends StatefulWidget {
|
||||
|
||||
class _BottomAppBarState extends State<BottomAppBar> {
|
||||
late ValueListenable<ScaffoldGeometry> geometryListenable;
|
||||
final GlobalKey materialKey = GlobalKey();
|
||||
static const double _defaultElevation = 8.0;
|
||||
|
||||
@override
|
||||
@ -285,10 +287,11 @@ class _BottomAppBarState extends State<BottomAppBar> {
|
||||
final NotchedShape? notchedShape = widget.shape ?? babTheme.shape;
|
||||
final CustomClipper<Path> clipper = notchedShape != null
|
||||
? _BottomAppBarClipper(
|
||||
geometry: geometryListenable,
|
||||
shape: notchedShape,
|
||||
notchMargin: widget.notchMargin,
|
||||
)
|
||||
geometry: geometryListenable,
|
||||
shape: notchedShape,
|
||||
materialKey: materialKey,
|
||||
notchMargin: widget.notchMargin,
|
||||
)
|
||||
: const ShapeBorderClipper(shape: RoundedRectangleBorder());
|
||||
final double elevation = widget.elevation ?? babTheme.elevation ?? _defaultElevation;
|
||||
final Color color = widget.color ?? babTheme.color ?? Theme.of(context).bottomAppBarColor;
|
||||
@ -299,6 +302,7 @@ class _BottomAppBarState extends State<BottomAppBar> {
|
||||
color: effectiveColor,
|
||||
clipBehavior: widget.clipBehavior,
|
||||
child: Material(
|
||||
key: materialKey,
|
||||
type: MaterialType.transparency,
|
||||
child: widget.child == null
|
||||
? null
|
||||
@ -312,6 +316,7 @@ class _BottomAppBarClipper extends CustomClipper<Path> {
|
||||
const _BottomAppBarClipper({
|
||||
required this.geometry,
|
||||
required this.shape,
|
||||
required this.materialKey,
|
||||
required this.notchMargin,
|
||||
}) : assert(geometry != null),
|
||||
assert(shape != null),
|
||||
@ -320,17 +325,21 @@ class _BottomAppBarClipper extends CustomClipper<Path> {
|
||||
|
||||
final ValueListenable<ScaffoldGeometry> geometry;
|
||||
final NotchedShape shape;
|
||||
final GlobalKey materialKey;
|
||||
final double notchMargin;
|
||||
|
||||
// Returns the top of the BottomAppBar in global coordinates.
|
||||
double get bottomNavigationBarTop {
|
||||
final RenderBox? box = materialKey.currentContext?.findRenderObject() as RenderBox?;
|
||||
return box?.localToGlobal(Offset.zero).dy ?? 0;
|
||||
}
|
||||
|
||||
@override
|
||||
Path getClip(Size size) {
|
||||
// button is the floating action button's bounding rectangle in the
|
||||
// coordinate system whose origin is at the appBar's top left corner,
|
||||
// or null if there is no floating action button.
|
||||
final Rect? button = geometry.value.floatingActionButtonArea?.translate(
|
||||
0.0,
|
||||
geometry.value.bottomNavigationBarTop! * -1.0,
|
||||
);
|
||||
final Rect? button = geometry.value.floatingActionButtonArea?.translate(0.0, bottomNavigationBarTop * -1.0);
|
||||
return shape.getOuterPath(Offset.zero & size, button?.inflate(notchMargin));
|
||||
}
|
||||
|
||||
|
@ -381,6 +381,40 @@ void main() {
|
||||
physicalShape = tester.widget(find.byType(PhysicalShape));
|
||||
expect(physicalShape.clipBehavior, Clip.antiAliasWithSaveLayer);
|
||||
});
|
||||
|
||||
testWidgets('BottomAppBar with shape when Scaffold.bottomNavigationBar == null', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/80878
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
|
||||
floatingActionButton: FloatingActionButton(
|
||||
backgroundColor: Colors.green,
|
||||
child: const Icon(Icons.home),
|
||||
onPressed: () {},
|
||||
),
|
||||
body: Stack(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
color: Colors.amber,
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: BottomAppBar(
|
||||
color: Colors.green,
|
||||
shape: const CircularNotchedRectangle(),
|
||||
child: Container(height: 50),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(tester.getRect(find.byType(FloatingActionButton)), const Rect.fromLTRB(372, 528, 428, 584));
|
||||
expect(tester.getSize(find.byType(BottomAppBar)), const Size(800, 50));
|
||||
});
|
||||
}
|
||||
|
||||
// The bottom app bar clip path computation is only available at paint time.
|
||||
|
Loading…
x
Reference in New Issue
Block a user