I’m trying to recreate this effect in Flutter, I initially created it in Angular using CSS.
Basically imagine a bottom NavBar sitting behind a container with bottom border radius.
I’m pretty new to Flutter and still learning things, but there doesn’t seem to be an obvious way to accomplish this. I do know about Stack but I’m not sure if I can combine it with BottomNavigationBar (or if it’s good practice seeing how a property on Scaffold is made specifically for it)
Here’s what I tried using ClipPath.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
extendBody: true,
body: Column(
children: [
Expanded(
child: Container(
height: 100,
decoration: const BoxDecoration(
color: Colors.red,
),
))
],
),
bottomNavigationBar: const NavBar(),
),
);
}
}
class NavBar extends StatefulWidget {
const NavBar({super.key});
@override
State<NavBar> createState() => _NavBarState();
}
class _NavBarState extends State<NavBar> {
static const List<BottomNavigationBarItem> _items = <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home_outlined),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: 'Search',
),
BottomNavigationBarItem(
icon: Icon(Icons.messenger_outline),
label: 'Message',
),
BottomNavigationBarItem(
icon: Icon(Icons.person_outlined),
label: 'Profile',
),
];
final int _selectedIndex = 0;
@override
Widget build(BuildContext context) {
return ClipPath(
clipper: CustomShapeClipper(),
child: SizedBox(
height: 75,
child: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: _items,
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
unselectedItemColor: Colors.black,
showUnselectedLabels: true,
showSelectedLabels: true,
),
),
);
}
}
class CustomShapeClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
final path = Path();
double cornerHeight = size.height - 75;
path.moveTo(0, size.height);
path.lineTo(0, cornerHeight); // Raise the starting point of the curve to the top right corner
path.quadraticBezierTo(size.width * 0.5, size.height - 50, size.width, cornerHeight); // Adjust the control points to flatten the curve
path.lineTo(size.width, size.height);
path.close();
return path;
}
@override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
return false;
}
}
This is what it looks like:
Is there a better way to accomplish this?
Any help would really be appreciated.
2
Answers
You should use
CustomPainter
fixed code:
result:
The simple approach is you can use
ClipRRect
to clip your body, and by using this method you can change the radius easily by changingborderRadius
property.The code below is to demonstrate the clipping result with
ClipRRect
toListView
And this is the result:
Hopefully it can solve your problem, Thanks 😉