Flutter : Incorrect use of ParentDataWidget - flutter

I have a screen layout like newsfeed instagram
When I come to this screen I got issue like this
problem
I have parent screen where place the bottom bar :
return Scaffold(
body: homeScreenItems[_page],
bottomNavigationBar: Offstage(
offstage: isSwipeLeft,
child: BottomNavigationBar(
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
label: '',
backgroundColor: primaryColor,
),
BottomNavigationBarItem(
icon: Icon(
Icons.search,
),
label: '',
backgroundColor: primaryColor),
BottomNavigationBarItem(
icon: Icon(
Icons.video_camera_back_outlined,
),
label: '',
),
BottomNavigationBarItem(
icon: Icon(
Icons.favorite,
),
label: '',
backgroundColor: primaryColor,
),
BottomNavigationBarItem(
icon: Icon(
Icons.person,
),
label: '',
backgroundColor: primaryColor,
),
],
onTap: onPageChanged,
currentIndex: _page,
backgroundColor: (_page != 2) ? primaryColor : blackColor,
type: BottomNavigationBarType.fixed,
selectedItemColor: (_page != 2) ? blackColor : primaryColor,
unselectedItemColor: secondaryColor,
),
),
);
This is the place where I code of newsfeed:
#override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;
return Scaffold(
backgroundColor:
width > webScreenSize ? webBackgroundColor : primaryColor,
appBar: width > webScreenSize
? null
: AppBar(
backgroundColor: primaryColor,
centerTitle: false,
title: SvgPicture.asset(
'assets/ic_instagram.svg',
color: blackColor,
height: 32,
),
actions: [
IconButton(
icon: const Icon(
Icons.add_box_outlined,
color: blackColor,
),
onPressed: () {},
),
IconButton(
icon: const Icon(
Icons.messenger_outline_rounded,
color: blackColor,
),
onPressed: onPress,
),
],
automaticallyImplyLeading: false,
),
body: PageStorage(
bucket: bucketGlobal,
child: ListView.builder(
itemBuilder: (context, index) {
return ItemFeed(
userModel: DataDefault.userModelDemo,
index: index,
);
},
itemCount: DataDefault.userModelDemo.length,
key: PageStorageKey<String>('listFeed'),
shrinkWrap: true,
padding: EdgeInsets.all(5),
scrollDirection: Axis.vertical,
),
),
);
Finally is where I placed feed_Item:
Widget buildFeedItem(List userModel, int index) {
return Column(
children: [
//header
Row(
children: [
CircleAvatar(
backgroundImage: AssetImage(
userModel[index]['userAvaUrl'],
),
),
SizedBox(
width: 5,
),
Text(
userModel[index]['userName'],
),
],
),
SizedBox(
height: 15,
),
//image post
GestureDetector(
onDoubleTap: () {
setState(() {
isLikeAnimating = true;
isHeartAnimating = true;
});
},
child: Stack(
alignment: Alignment.center,
children: [
// list postUrl
SliderImage(
listPost: userModel[index]['postUrl'],
),
AnimatedOpacity(
duration: const Duration(milliseconds: 200),
opacity: isLikeAnimating ? 1 : 0,
child: LikeAnimation(
isAnimating: isLikeAnimating,
child: Icon(
Icons.favorite,
color: isHeartAnimating ? errorColor : primaryColor,
size: 100,
),
duration: const Duration(
milliseconds: 400,
),
onEnd: () {
setState(() {
isLikeAnimating = false;
});
},
),
),
],
),
),
SizedBox(
height: 10,
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
// color: blueColor,
child: Row(
children: [
//icon like
CustomIcon(
child: Icon(
isHeartAnimating
? Icons.favorite_rounded
: Icons.favorite_border,
color: isHeartAnimating ? errorColor : blackColor,
size: 30,
),
onPress: () {
setState(() {
isLikeAnimating = true;
isHeartAnimating = !isHeartAnimating;
});
},
isAnimating: isLikeAnimating,
onEnd: () {
setState(
() {
isLikeAnimating = false;
},
);
},
),
SizedBox(
width: 10,
),
//icon comment
CustomIcon(
child: Icon(
Icons.chat_bubble_outline,
color: blackColor,
size: 30,
),
onPress: () {
setState(() {
isCommentAnimating = true;
});
},
isAnimating: isCommentAnimating,
onEnd: () {
setState(
() {
isCommentAnimating = false;
},
);
},
),
SizedBox(
width: 10,
),
//icon share
CustomIcon(
child: Icon(
Icons.send,
color: blackColor,
size: 30,
),
onPress: () {
setState(() {
isShareAnimating = true;
});
},
isAnimating: isShareAnimating,
onEnd: () {
setState(
() {
isShareAnimating = false;
},
);
},
),
//icon save
Expanded(
child: Align(
alignment: Alignment.bottomRight,
child: CustomIcon(
child: Icon(
isSave
? Icons.bookmark_added_rounded
: Icons.bookmark_border,
color: isSave ? saveColor : blackColor,
size: 30,
),
onPress: () {
setState(() {
isSaveAnimating = true;
isSave = !isSave;
});
},
isAnimating: isSaveAnimating,
onEnd: () {
setState(
() {
isSaveAnimating = false;
},
);
},
),
),
),
],
),
),
),
],
);
}
#override
Widget build(BuildContext context) {
return Container(
key: PageStorageKey<String>('listFeed'),
child: buildFeedItem(
widget.userModel,
widget.index,
),
);
}
Where did I do wrong? Please help me

Positioned need a StackParentData as it's parent.
But Column is not.
Put Positioned in Stack may resolve your problem.

Related

Flutter: save position indicator of slider image whenever change screen

I'm trying to save a position of indicator slider image, when I change to another page, the position of image works, but the indicator is not. I use PageStorage key to save the position. This is where I place a list of slider image:
body: PageStorage(
bucket: bucketGlobal,
child: ListView.builder(
itemBuilder: (context, index) {
return ItemFeed(
userModel: DataDefault.userModelDemo,
index: index,
);
},
itemCount: DataDefault.userModelDemo.length,
key: PageStorageKey<String>('listFeed'),
shrinkWrap: true,
padding: EdgeInsets.all(5),
scrollDirection: Axis.vertical,
),
),
);
And this is the code for its item:
Widget buildFeedItem(List userModel, int index, String text) {
return Column(
children: [
//header
Row(
children: [
CircleAvatar(
backgroundImage: AssetImage(
userModel[index]['userAvaUrl'],
),
),
SizedBox(
width: 5,
),
Text(
userModel[index]['userName'],
),
],
),
SizedBox(
height: 15,
),
//image post
GestureDetector(
onDoubleTap: () {
setState(() {
isLikeAnimating = true;
isHeartAnimating = true;
});
},
child: Stack(
alignment: Alignment.center,
children: [
// list postUrl
SliderImage(
onPageChange: (index, reason) {
setState(() {
currentIndex = index;
});
},
controller: sliderController,
key: PageStorageKey<String>('listFeed'),
listPost: userModel[index]['postUrl'],
),
Positioned(
top: 0,
right: 10,
child: Container(
margin: EdgeInsets.only(
top: 10,
),
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: blackColor.withOpacity(0.6),
borderRadius: BorderRadius.circular(20),
),
child: Text(
(currentIndex + 1).toString() +
'/' +
userModel[index]['postUrl'].length.toString(),
key: PageStorageKey<String>('listFeed'),
style: TextStyle(
color: primaryColor,
),
),
),
),
AnimatedOpacity(
duration: const Duration(milliseconds: 200),
opacity: isLikeAnimating ? 1 : 0,
child: LikeAnimation(
isAnimating: isLikeAnimating,
child: Icon(
Icons.favorite,
color: isHeartAnimating ? errorColor : primaryColor,
size: 100,
),
duration: const Duration(
milliseconds: 400,
),
onEnd: () {
setState(() {
isLikeAnimating = false;
});
},
),
),
],
),
),
SizedBox(
height: 10,
),
Container(
// color: blueColor,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//icon like
CustomIcon(
child: Icon(
isHeartAnimating
? Icons.favorite_rounded
: Icons.favorite_border,
color: isHeartAnimating ? errorColor : blackColor,
size: 30,
),
onPress: () {
setState(() {
isLikeAnimating = true;
isHeartAnimating = !isHeartAnimating;
});
},
isAnimating: isLikeAnimating,
onEnd: () {
setState(
() {
isLikeAnimating = false;
},
);
},
),
SizedBox(
width: 10,
),
//icon comment
CustomIcon(
child: Icon(
Icons.chat_bubble_outline,
color: blackColor,
size: 30,
),
onPress: () {
setState(() {
isCommentAnimating = true;
});
},
isAnimating: isCommentAnimating,
onEnd: () {
setState(
() {
isCommentAnimating = false;
},
);
},
),
SizedBox(
width: 10,
),
//icon share
CustomIcon(
child: Icon(
Icons.send,
color: blackColor,
size: 30,
),
onPress: () {
setState(() {
isShareAnimating = true;
});
},
isAnimating: isShareAnimating,
onEnd: () {
setState(
() {
isShareAnimating = false;
},
);
},
),
Spacer(),
Align(
alignment: Alignment.center,
child: AnimatedSmoothIndicator(
activeIndex: currentIndex,
count: userModel[index]['postUrl'].length,
effect: WormEffect(
activeDotColor: blueColor,
dotColor: secondaryColor.withOpacity(0.4),
dotHeight: 5,
dotWidth: 5,
spacing: 2.0,
),
),
),
Spacer(),
],
),
),
],
);
}
#override
Widget build(BuildContext context) {
return Container(
key: PageStorageKey<String>('listFeed'),
child: buildFeedItem(
widget.userModel,
widget.index,
'CC',
),
);
}
Why does the slider image work but the indicator is not?
How can I fix it? Please help

how to change navbar item color when it click

I want to change the color when I click the nav bar item. how to do this. appreciate your help on this. below I have ad my code for your reference. ............... ............. ............ ............. ........... ............ ............. ........... ............. ........... .......... .......... ........... ........... .........
class BottomNavigation extends StatefulWidget {
const BottomNavigation({Key? key}) : super(key: key);
#override
State<BottomNavigation> createState() => _BottomNavigationState();
}
class _BottomNavigationState extends State<BottomNavigation> {
int _selectedIndex = 0;
int _selectedTab = 0;
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
color: backgroundWhite,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
enableFeedback: false,
onPressed: () {
Get.to(HomeScreenCompanyList());
},
icon: const Icon(
Icons.home_outlined,
color: textGrey,
size: 25,
),
),
IconButton(
enableFeedback: false,
onPressed: () {
Get.to(CompanyList());
},
icon: const Icon(
Icons.folder_outlined,
color: textGrey,
size: 25,
),
),
IconButton(
enableFeedback: false,
onPressed: () {
Get.to(Category());
},
icon: const Icon(
Icons.search,
color: textGrey,
size: 25,
),
),
IconButton(
enableFeedback: false,
onPressed: () {
Get.to(Services());
},
icon: const Icon(
Icons.edit_note_outlined,
color: textGrey,
size: 25,
),
),
IconButton(
enableFeedback: false,
onPressed: () {},
icon: const Icon(
Icons.person_outline,
color: textGrey,
size: 25,
),
),
],
),
);
}
}
class _BottomNavigationState extends State<AllPageListView> {
int _selectedIndex = 0;
int _selectedTab = 0;
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: Center(
child: Text('Body'),
)),
],
),
bottomNavigationBar: Container(
decoration: const BoxDecoration(
// color: backgroundWhite,
color: Colors.white,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
enableFeedback: false,
onPressed: () {
_onItemTapped(1);
},
icon: Icon(
Icons.home_outlined,
color: _selectedIndex == 1 ? Colors.red : Colors.black,
size: 25,
),
),
IconButton(
enableFeedback: false,
onPressed: () {
_onItemTapped(2);
},
icon: Icon(
Icons.folder_outlined,
color: _selectedIndex == 2 ? Colors.red : Colors.black,
size: 25,
),
),
IconButton(
enableFeedback: false,
onPressed: () {
_onItemTapped(3);
},
icon: Icon(
Icons.search,
color: _selectedIndex == 3 ? Colors.red : Colors.black,
size: 25,
),
),
IconButton(
enableFeedback: false,
onPressed: () {
_onItemTapped(4);
},
icon: Icon(
Icons.edit_note_outlined,
color: _selectedIndex == 4 ? Colors.red : Colors.black,
size: 25,
),
),
IconButton(
enableFeedback: false,
onPressed: () {
_onItemTapped(5);
},
icon: Icon(
Icons.person_outline,
color: _selectedIndex == 5 ? Colors.red : Colors.black,
size: 25,
),
),
],
),
),
);
}
}

Show Bottom Modal Sheet above the Bottom Navigation Bar

Here in the below image I have added showModalBottomSheet on clicking on the item of "Bottom Navigation Bar", but the BottomNavigationBar is hidden by the modal sheet, So I want to make it visible even the bottom sheet is present. Can anyone please anyone help me out.
This is my bottom navigation code:
Widget _bottomNavigationBar() {
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
key: scaffoldState,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.branding_watermark_outlined),
label: 'Brands',
),
BottomNavigationBarItem(
icon: Icon(Icons.category),
label: 'Category',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
)
],
currentIndex: _selectedIndex,
selectedItemColor: AppColors.blue,
onTap: (newIndex) => {
if (newIndex == 1)
{showBrandsBottomSheet(context)}
else if (newIndex == 2)
{showCategoryBottomSheet(context)}
else
{
setState(() {
_selectedIndex = newIndex;
})
}
});
}
Here is my code for bottom model sheet:
showBrandsBottomSheet(BuildContext context) {
return showModalBottomSheet<void>(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(15.0), topRight: Radius.circular(15.0)),
),
context: context,
useRootNavigator: true,
isScrollControlled: true,
builder: (BuildContext _) {
return Container(
color: Colors.white,
height: MediaQuery.of(context).size.height / 2,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 5, top: 3),
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: const Align(
alignment: Alignment.topRight,
child: Icon(Icons.close)),
),
),
Container(
color: Colors.white,
height: 350,
child: ListView.builder(
key: Key('builder ${_selected.toString()}'), //a
scrollDirection: Axis.vertical,
// shrinkWrap: true,
// physics: NeverScrollableScrollPhysics(),
itemCount: brandList.length,
itemBuilder: (BuildContext context, int index) {
return Theme(
data: Theme.of(context)
.copyWith(dividerColor: Colors.white),
child: ExpansionTile(
// tilePadding: const EdgeInsets.all(0),
key: Key(index.toString()), //attention
initiallyExpanded: index == _selected, //attention
collapsedIconColor: Colors.blue,
iconColor: Colors.blue,
backgroundColor: Colors.white,
title: Text(
brandList[index],
style: const TextStyle(
fontSize: 13.0,
color: Colors.black,
fontWeight: FontWeight.w600),
),
children: <Widget>[
Container(
color: Colors.blue[50],
child: Column(
children: _buildExpandableBrands(brandList),
),
),
],
onExpansionChanged: ((newState) {
if (newState) {
setState(() {
const Duration(seconds: 20000);
_selected = index;
});
} else {
setState(() {
_selected = -1;
});
}
}),
));
},
),
),
],
),
),
);
},
);
}
set useRootNavigator=true.This will display model sheet above all other content.
showModalBottomSheet(
context: context,
isScrollControlled: true,
useRootNavigator: true,
builder: (context) {
return BottomBarView(
);
});
Finally, this question helped me in getting this done.
Here is my working code:
Widget _bottomNavigationBar() {
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
key: scaffoldState,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.branding_watermark_outlined),
label: 'Brands',
),
BottomNavigationBarItem(
icon: Icon(Icons.category),
label: 'Category',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
)
],
currentIndex: _selectedIndex,
selectedItemColor: AppColors.blue,
onTap: (newIndex) => {
if (newIndex == 1)
{
_scaffoldKey.currentState?.showBottomSheet((_) => Container(
child: showBrandsBottomSheet(),
))
}
else if (newIndex == 2)
{
{
_scaffoldKey.currentState?.showBottomSheet((_) => Container(
child: showCategoryBottomSheet(),
))
}
}
else
{
setState(() {
_selectedIndex = newIndex;
})
}
});
}
showBrandsBottomSheet:
showBrandsBottomSheet() {
return Container(
color: Colors.white,
height: MediaQuery.of(context).size.height / 2,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 5, top: 3),
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: const Align(
alignment: Alignment.topRight, child: Icon(Icons.close)),
),
),
Container(
color: Colors.white,
height: 350,
child: ListView.builder(
key: UniqueKey(),
scrollDirection: Axis.vertical,
itemCount: brandList.length,
itemBuilder: (BuildContext context, int index) {
cardKeyList.add(GlobalKey(debugLabel: "index :$index"));
return Theme(
data: Theme.of(context)
.copyWith(dividerColor: Colors.white),
child: ExpansionTileCard(
key: cardKeyList[index],
initiallyExpanded: false,
title: Text(
brandList[index],
style: const TextStyle(
fontSize: 13.0,
color: Colors.black,
fontWeight: FontWeight.w600),
),
children: <Widget>[
Container(
color: Colors.blue[50],
child: Column(
children: _buildExpandableBrands(brandList),
),
),
],
onExpansionChanged: (value) {
if (value) {
Future.delayed(const Duration(milliseconds: 200),
() {
for (var i = 0; i < cardKeyList.length; i++) {
if (index != i) {
cardKeyList[i].currentState?.collapse();
}
}
});
}
},
));
},
),
),
],
),
),
);
}
Now it is started showing above the bottom navigation.

What to do to make work button with SpeedDial?

I have a problem with adding options after expanding a button(app has bottomAppBar and FloatingAction).
The button works, but when I go to options and want to go to the EditDogScreen page, it does not take me there.The whole thing has been added to the buttonBar, will such a reference work? and how to change it.
I am using SpeedDial Widget for FAB
SpeedDial buildSpeedDial() {
return SpeedDial(
animatedIcon: AnimatedIcons.menu_close,
animatedIconTheme: IconThemeData(size: 22.0),
// child: Icon(Icons.add),
onOpen: () => print('OPENING DIAL'),
onClose: () => print('DIAL CLOSED'),
visible: dialVisible,
curve: Curves.bounceIn,
children: [
**SpeedDialChild(
label: 'First',
labelStyle: TextStyle(fontSize: 18.0),
backgroundColor: Colors.red,
child: GestureDetector(
onLongPress: () async {
await Navigator.of(context).pushNamed(EditDogScreen.id);
await backend.getDogs();
setState(() {});
},
child: Icon(
Icons.add,
),
),
),**
SpeedDialChild(
child: Icon(Icons.brush, color: Colors.white),
backgroundColor: Colors.green,
onTap: () => print('SECOND CHILD'),
label: 'Second Child',
labelStyle: TextStyle(fontWeight: FontWeight.w500),
labelBackgroundColor: Colors.green,
),
SpeedDialChild(
child: Icon(Icons.keyboard_voice, color: Colors.white),
backgroundColor: Colors.blue,
onTap: () => print('THIRD CHILD'),
labelWidget: Container(
color: Colors.blue,
margin: EdgeInsets.only(right: 10),
padding: EdgeInsets.all(6),
child: Text('Custom Label Widget'),
),
),
],
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
// stable top bar for all screens with bottombar
appBar: AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => WelcomeScreen()));
}),
],
),
body: _pageOptions[_selectedPage],
bottomNavigationBar: CurvedNavigationBar(
backgroundColor: Colors.blue.withOpacity(0.7),
color: Colors.blue.withOpacity(0.5),
index: _selectedPage,
buttonBackgroundColor: Colors.white,
// backgroundColor: Colors.blue,
animationCurve: Curves.easeInOut,
animationDuration: Duration(milliseconds: 500),
onTap: (int index) {
setState(() {
_selectedPage = index;
});
},
letIndexChange: (index) => true,
items: <Widget>[
Icon(Icons.home, size: 30),
Icon(Icons.list, size: 30),
**buildSpeedDial(),**
Icon(Icons.call_split, size: 30),
Icon(Icons.perm_identity, size: 30),
],
),
);
}
}

How do you create a Flutter bottom navigation with a top line on active menu item?

I have the following Flutter bottom navigation bar
And I would like to add a top-line or boarder for active items like so
Is that even possible, my code is straight forward.
#override
Widget build(BuildContext context) {
return Scaffold(
body: _tabs[_tabIndex],
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.white,
selectedLabelStyle: TextStyle(fontSize: 14),
selectedItemColor: Theme.of(context).accentColor,
unselectedLabelStyle: TextStyle(fontSize: 14.0),
unselectedItemColor: Color(0xff546481),
type: BottomNavigationBarType.fixed,
showSelectedLabels: true,
showUnselectedLabels: true,
currentIndex: _tabIndex,
onTap: (int index) {
setState(() {
_tabIndex = index;
});
},
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home_outlined),
label: 'HOME',
),
BottomNavigationBarItem(
icon: Icon(Icons.history_outlined),
label: 'HISTORY',
),
BottomNavigationBarItem(
icon: Icon(Icons.person_outline),
label: 'PROFILE',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings_outlined),
label: 'SETTINGS',
),
],
),
);
}
}
there are some packages can achieve this effect:
titled_navigation_bar
bottomNavigationBar: TitledBottomNavigationBar(
currentIndex: 2, // Use this to update the Bar giving a position
onTap: (index){
print("Selected Index: $index");
},
items: [
TitledNavigationBarItem(title: Text('Home'), icon: Icons.home),
TitledNavigationBarItem(title: Text('Search'), icon: Icons.search),
TitledNavigationBarItem(title: Text('Bag'), icon: Icons.card_travel),
TitledNavigationBarItem(title: Text('Orders'), icon: Icons.shopping_cart),
TitledNavigationBarItem(title: Text('Profile'), icon: Icons.person_outline),
]
)
bottom_indicator_bar
class _HomePageState extends State<HomePage> {
final List<BottomIndicatorNavigationBarItem> items = [
BottomIndicatorNavigationBarItem(icon: Icons.home),
BottomIndicatorNavigationBarItem(icon: Icons.search),
BottomIndicatorNavigationBarItem(icon: Icons.settings),
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Indicator Bottom Bar"),
backgroundColor: Colors.teal,
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
],
),
),
bottomNavigationBar: BottomIndicatorBar(
onTap: (index) => {},
items: items,
activeColor: Colors.teal,
inactiveColor: Colors.grey,
indicatorColor: Colors.teal,
),
);
}
}
You can use a TabBar instead of a BottomNavigationBar using a custom decoration:
class TopIndicator extends Decoration {
#override
BoxPainter createBoxPainter([VoidCallback? onChanged]) {
return _TopIndicatorBox();
}
}
class _TopIndicatorBox extends BoxPainter {
#override
void paint(Canvas canvas, Offset offset, ImageConfiguration cfg) {
Paint _paint = Paint()
..color = Colors.cyan
..strokeWidth = 5
..isAntiAlias = true;
canvas.drawLine(offset, Offset(cfg.size!.width + offset.dx, 0), _paint);
}
}
Then pass the decoration to the TapBar using TapBar(indicator: TopIndicator ...).
To use the TabBar as the Scaffold.bottomNavigationBar, you will most likely want to wrap it in a Material to apply a background color:
Scaffold(
bottomNavigationBar: Material(
color: Colors.white,
child: TabBar(
indicator: TopIndicator(),
tabs: const <Widget>[
Tab(icon: Icon(Icons.home_outlined), text: 'HOME'),
...
],
),
),
...
)
Thanks Ara Kurghinyan for the original idea.
Column(
children: [
pageIndex == 2
? Container(
height: 5.w,
width: 35.h,
alignment: Alignment.center,
// margin: const EdgeInsets.only(left: 5),
decoration: const BoxDecoration(
color: Colors.teal,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(
3,
),
bottomRight: Radius.circular(3)),
),
// height: 5,
// width: 35,
)
: SizedBox(
height: 5.w,
width: 35.h,
),
SizedBox(
height: 4.h,
),
Flexible(
child: Container(
height: 25.h,
width: 25.w,
// alignment: Alignment.lerp(
// Alignment.bottomLeft, Alignment.bottomRight, 1),
decoration: BoxDecoration(
// color: Colors.red,
border: Border.all(
width: 1,
color: Colors.black,
),
borderRadius: const BorderRadius.all(
Radius.circular(20),
),
),
child: IconButton(
iconSize: 25,
alignment: Alignment.center,
padding: const EdgeInsets.only(top: 4, bottom: 4),
visualDensity:
const VisualDensity(horizontal: -4, vertical: -4),
enableFeedback: false,
onPressed: () {
setState(() {
pageIndex = 2;
});
},
icon: pageIndex == 2
? Image.asset(
'assets/icons/icons8-alarm-50.png',
height: 24.h,
color: Colors.black,
// size: 35.sm,
)
: Image.asset(
'assets/icons/icons8-alarm-50.png',
color: Colors.black,
// size: 35.sm,
)),
),
),
pageIndex == 2
? Container(
height: 15.h,
width: 60.w,
alignment: Alignment.lerp(
Alignment.centerLeft, Alignment.centerRight, 0.75),
child: Text(
'Reminder',
style: GoogleFonts.lato(
textStyle: const TextStyle(
fontSize: 12, fontWeight: FontWeight.bold),
),
),
)
: Container(),
],
),