I want to create BottomAppBar
with rounded corners, circular notched rectangle and material shadow.
The problem is that when I add rounded corners to BottomAppBar
by wrapping it with ClipRRect
widget I lose material shadow.
BottomAppBar without rounded corners, but with Material shadow. Please ignore wrong aligned notch.
BottomAppBar wrapped in ClipRRect widget, but without shadow. Again please ignore wrong aligned notch:
How to achieve rounded corners with notch and material shadow?
Full code:
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
extendBody: true,
body: Container(
color: Colors.amber,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Transform.translate(
offset: Offset(0, -10),
child: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
elevation: 2.0,
),
),
bottomNavigationBar: BottomNavigationView(),
),
);
}
}
class BottomNavigationView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Transform.translate(
offset: Offset(0.0, -10),
child: Container(
margin: EdgeInsets.only(left: 20, right: 20),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(30),
),
child: BottomAppBar(
shape: CircularNotchedRectangle(),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.accessibility_new),
],
),
_buildMiddleTabItem(),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.accessibility_new),
],
)
],
),
),
),
),
);
}
Widget _buildMiddleTabItem() {
return Expanded(
child: SizedBox(
height: 60,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 24),
Text(''),
],
),
),
);
}
}
You can create your own ShapeBorder.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
extendBody: true,
body: Container(
color: Colors.amber,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Transform.translate(
offset: Offset(0, -10),
child: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
elevation: 2.0,
),
),
bottomNavigationBar: BottomNavigationView(),
),
);
}
}
class BottomNavigationView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Transform.translate(
offset: Offset(0.0, -10),
child: Container(
margin: EdgeInsets.symmetric(horizontal: 10),
padding: EdgeInsets.symmetric(horizontal: 20),
decoration: ShapeDecoration(
color: Colors.white,
shape: MyBorderShape(),
shadows: [
BoxShadow(
color: Colors.black38, blurRadius: 8.0, offset: Offset(1, 1)),
],
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.accessibility_new),
],
),
_buildMiddleTabItem(),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.accessibility_new),
],
)
],
),
),
);
}
Widget _buildMiddleTabItem() {
return Expanded(
child: SizedBox(
height: 60,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 24),
Text(''),
],
),
),
);
}
}
class MyBorderShape extends ShapeBorder {
MyBorderShape();
@override
EdgeInsetsGeometry get dimensions => EdgeInsets.zero;
@override
Path getInnerPath(Rect rect, {TextDirection textDirection}) => null;
double holeSize = 70;
@override
Path getOuterPath(Rect rect, {TextDirection textDirection}) {
print(rect.height);
return Path.combine(
PathOperation.difference,
Path()
..addRRect(
RRect.fromRectAndRadius(rect, Radius.circular(rect.height / 2)))
..close(),
Path()
..addOval(Rect.fromCenter(
center: rect.center.translate(0, -rect.height / 2),
height: holeSize,
width: holeSize))
..close(),
);
}
@override
void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {}
@override
ShapeBorder scale(double t) => this;
}