I made a custom NavBar but it doesn’t look natural. It should look like the Nav bar is in front of the drink card but instead It looks like it has its own block section. Is there a way for me to remove the SafeAre around the Nav Bar?
Here is the code:
Widget commonTabScene(String tabName){
return Container(
alignment: Alignment.center,
child: Text(tabName, style: const TextStyle(fontSize: 28),),
);
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _RiveAppHomeState();
}
class _RiveAppHomeState extends State<HomeScreen> {
Widget _tabBody = Container(color: RiveAppTheme.background);
final List<Widget> _screens = [
const CategoriesScreen(),
commonTabScene('Search'),
commonTabScene('Timer'),
commonTabScene('Bell'),
commonTabScene('User'),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body:_tabBody,
bottomNavigationBar: CustomTabBar(
onTabChange: (tabIndex) {
setState(() {
_tabBody = _screens[tabIndex];
});
},
),
);
}
}
Here Is the Custom Nav code.
custom_nav_bar:*
class CustomTabBar extends StatefulWidget {
const CustomTabBar({super.key, required this.onTabChange});
final Function(int tabIndex) onTabChange;
@override
State<CustomTabBar> createState() => _CustomTabBarState();
}
class _CustomTabBarState extends State<CustomTabBar> {
final List<TabItem> _icons = TabItem.tabItemsList;
int _selectedTab = 0;
void _onRiveIconInit(Artboard artboard, index) {
final controller = StateMachineController.fromArtboard(
artboard, _icons[index].stateMachine);
artboard.addController(controller!);
_icons[index].status = controller.findInput<bool>('active') as SMIBool;
}
void onTabPress(int index) {
if (_selectedTab != index){
setState(() {
_selectedTab = index;
});
widget.onTabChange(index);
// Starts Animation
_icons[index].status!.change(true);
// Stops Animation
Future.delayed(const Duration(seconds: 1), () {
_icons[index].status!.change(false);
});
}
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Container(
margin: const EdgeInsets.fromLTRB(24, 0, 24, 8),
padding: const EdgeInsets.all(1),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24),
gradient: LinearGradient(colors: [
Colors.white.withOpacity(0.5),
Colors.white.withOpacity(0),
]),
),
child: Container(
decoration: BoxDecoration(
color: RiveAppTheme.background2.withOpacity(0.8),
borderRadius: BorderRadius.circular(24),
boxShadow: [
BoxShadow(
color: RiveAppTheme.background2.withOpacity(0.3),
blurRadius: 20,
offset: const Offset(0, 20),
)
]),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(_icons.length, (index) {
TabItem icon = _icons[index];
return Expanded(
key: icon.id,
child: CupertinoButton(
padding: const EdgeInsets.all(12),
// Makes the widget smaller
child: AnimatedOpacity(
opacity: _selectedTab == index ? 1 : 0.5,
duration: const Duration(milliseconds: 200),
child: Stack(
clipBehavior: Clip.none,
alignment: Alignment.center,
children: [
Positioned(
top: -4,
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
height: 4,
width: _selectedTab == index ? 20 : 0,
decoration: BoxDecoration(
color: RiveAppTheme.accentColor,
borderRadius: BorderRadius.circular(2)
),
),
),
SizedBox(
height: 36,
width: 36,
child: RiveAnimation.asset(
'assets/samples/ui/rive_app/rive/iconss.riv',
// How to get specific Icon
stateMachines: [icon.stateMachine],
artboard: icon.artboard,
onInit: (artboard) {
_onRiveIconInit(artboard, index);
},
),
),
],
),
),
onPressed: () {
onTabPress(index);
},
),
);
}),
),
),
),
);
}
}
I’ve looked almost every where But I cannot find a specific answer for this question.
2
Answers
You can use
stack
with your nav bar on main screen widget instead ofbottomNavigationBar
property of scaffold, for examplewhere BaseScreen is a common widget for your scenes
Or smth like this.
But it’s better to create each screen as full screen with changing via navigator, not only one screen with different bodies.
You just have to use
extendBody: true
on the Scaffold.