Reduce top & bottom padding in BottomNavigationBar - flutter

I would like to reduce top and bottom padding of BottomNavigationBar but I want to keep the same icon height and the bar height to 50 pixels :
bottomNavigationBar: SizedBox(
height: 50,
child: BottomNavigationBar(
showSelectedLabels: false,
showUnselectedLabels: false,
type: BottomNavigationBarType.fixed,
elevation: 5.0,
currentIndex: 0,
items: buildBottomBarItems(),
),
)
the method to build bottom bar items :
List<BottomNavigationBarItem> buildBottomBarItems() {
List<BottomNavigationBarItem> _bottomBarItems = List();
List<String> _iconNames = ["home", "search", "plus", "heart"];
for (var i = 0; i < _iconNames.length; ++i) {
_bottomBarItems.add(
BottomNavigationBarItem(
icon: Container(
child: new Image.asset('assets/' + _iconNames[i] + '.png', width: 24, height: 24)
),
title: Text('')
)
);
}
}
(in the present case there is an overflow of 4.0 pixels). Thank you

To remove the default space in BottomNavigationBar set the selectedFontSize to 0.
It will remove the default space available for the text.
BottomNavigationBar(
selectedFontSize: 0.0,
)

Related

Pie chart issues in flutter

I'm using the fl_chart package to create an interactive Pie Chart for my application. Although the design came out fine, I'm facing the following issues with the functionality:
Tapping on a particular PieChartSectionData doesn't always select it and even tapping repeatedly doesn't help. It's always two out of the three that are tappable. Please note that the functionality works as it should for all the sections but there is no indication suggesting that the section tapped on was clicked. As defined in my code, every tap on a section should increase the radius and it's font size to make it stand out from the rest.
Every time a PieChartSectionData is clicked, it is supposed to navigate to a new page after a delay of 500 milliseconds. Although this works as expected, I cannot seem to come back to the previous page that has the Pie Chart on it using the phone's back button on the very first click. It is only after repeated clicks that it takes me back to the original page.
The chart seems to be clickable even beyond the PieChartSectionData. So like let's say if I tap an inch away from one of the sections, it tends to take me to that other page I need to navigate to. This shouldn't be the case.
Here is my code:
class ToDoListPieState extends State<ToDoListPie> {
int? index;
double? percent;
int? taskCount;
#override
Widget build(BuildContext context) {
final provider = Provider.of<TodaysTaskList>(context).getToDoList;
// TODO: implement build
return Stack(
children: [
PieChart(PieChartData(
borderData: FlBorderData(show: false),
pieTouchData: PieTouchData(
touchCallback: (FlTouchEvent event, pieTouchResponse) {
setState(() {
if (pieTouchResponse == null ||
pieTouchResponse.touchedSection == null) {
index = -1;
}
index = pieTouchResponse!.touchedSection!.touchedSectionIndex;
});
Future.delayed(const Duration(milliseconds: 500), () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => TaskList())); //This here is the event where clicking on a section should take us to the next page
});
print('Index: $index'); //This prints even if we click away from a section
},
),
sectionsSpace: 5,
centerSpaceRadius: 80,
sections: [
PieChartSectionData(
color: Colors.blue,
title: provider['upcoming'].length.toString(),
value: double.parse(provider['upcoming'].length.toString()),
radius: index == 0 ? 40 : 30,
titleStyle: TextStyle(fontSize: index == 0 ? 25 : 16)),
PieChartSectionData(
color: Colors.amber,
title: provider['today'].length.toString(),
value: double.parse(provider['today'].length.toString()),
radius: index == -1 ? 40 : 30,
titleStyle: TextStyle(fontSize: index == -1 ? 25 : 16)),
PieChartSectionData(
color: Colors.red,
title: provider['previous'].length.toString(),
value: double.parse(provider['previous'].length.toString()),
radius: index == 1 ? 40 : 30,
titleStyle: TextStyle(fontSize: index == 1 ? 25 : 16))
])),
Positioned(
left: 0,
top: SizeVariables.getHeight(context) * 0.18,
right: 0,
bottom: 0,
child: Column(
children: [
FittedBox(
fit: BoxFit.contain,
child: Text(
'${provider['upcoming'].length + provider['today'].length + provider['previous'].length}',
style: Theme.of(context)
.textTheme
.bodyText1!
.copyWith(fontSize: 25),
),
),
Text(
'Tasks',
style: Theme.of(context)
.textTheme
.bodyText1!
.copyWith(fontSize: 18),
)
],
),
)
],
);
}
}
Any help will be appreciated!

How to prevent not to rebuild UI inside Index Stack

I'm using index stack in home screen to show different screen at one time.
My Problem is that child widget is rebuilt again and make API call when ever I re-enter to any screen
home screen code:
final _currentPage =
context.select<MenuProvider, int>((provider) => provider.currentPage);
void _onItemTapped(int index) {
Provider.of<MenuProvider>(context, listen: false)
.updateCurrentPage(index);
}
List<MenuItem> mainMenu = [
MenuItem(
AppLocalizations.of(context)!.sd_title,
'Home',
Icons.home,
0,
),
MenuItem(
AppLocalizations.of(context)!.profile_title,
'Profile',
Icons.person,
1,
),
MenuItem(
AppLocalizations.of(context)!.sd_calculator,
'Calculator',
Icons.calculate_rounded,
2,
),
];
var screens = [
mainMenu[_currentPage].index == 0 ? const HomeFragment() : Container(),
mainMenu[_currentPage].index == 1 ? const Profile() : Container(),
mainMenu[_currentPage].index == 2
? LoanCalculatorScreen(isHome: true)
: Container(),
];
var container = Container(
alignment: Alignment.center,
color: Colors.white,
child: FadeIndexedStack(
index: mainMenu[_currentPage].index,
children: screens,
),
);
Container is used in body of Scaffold.
Bottom Navigation:
bottomNavigationBar: BottomNavigationBar(
items: mainMenu
.map(
(item) => BottomNavigationBarItem(
label: item.bottomTitle,
icon: Icon(
item.icon,
),
),
)
.toList(),
currentIndex: _currentPage,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
)
Home screen: As statefull to make a call on init state;
#override
void initState() {
var homeData = Provider.of<HomeProvider>(context, listen: false);
homeData.getOffersAndPartnersSlider();
super.initState();
}
I'm using Provider for state management and API call.
any suggestion will help me to write better code and make good performance.
I've Try Page View also same thing happen the inside child is rebuilt.
I just want to make The API call once.
To fix this I've made changes with Pages.
Declare list of pages above built method with PageStorageKey.
final List<Widget> pages = [
const HomeFragment(
key: PageStorageKey('Page1'),
),
const Profile(
key: PageStorageKey('Page2'),
),
Lo
LoanCalculatorScreen(key: const PageStorageKey('Page'), isHome: true),
];
And Call pages inside Indexed Stack Widgets Children
Container(
alignment: Alignment.center,
color: Colors.white,
child: FadeIndexedStack(
index: mainMenu[_currentPage].index,
children: pages,
),
)

BottomNavigationBar // Controlling Height with SizedBox leads to overflow

The goal:
Instead of using the hard coded height for the BottomNavigationBar, I want to size it as a fraction of the screen height.
My approach so far: I figured out that I can wrap the BottomNavigationBar in a SizedBox and control the height that way. Code at the botom.
The problem: I get overflows with the BottomNavigationBarItems on various devices.
I tried scaling the icons using the height of the SizedBox, but I need to make the items pretty small to avoid the overflow so that is not an option.
The code:
final bottomNavHeight = MediaQuery.of(context).size.heigth * 0.085;
bottomNavigationBar: SizedBox(
height: bottomNavHeight,
child: BottomNavigationBar(
onTap: _selectPage,
iconSize: bottomNavHeight * 0.45,
showSelectedLabels: false,
showUnselectedLabels: false,
currentIndex: _selectedPageIndex,
type: BottomNavigationBarType.fixed,
items: [
//home
BottomNavigationBarItem(
icon: Icon(Icons.home, color: _customColorScheme['Icon 1']),
activeIcon:
Icon(Icons.home, color: _customColorScheme['Icon 2']),
label: '',
),
//favorite
BottomNavigationBarItem(
icon:
Icon(Icons.favorite, color: _customColorScheme['Icon 1']),
activeIcon:
Icon(Icons.favorite, color: _customColorScheme['Icon 2']),
label: '',
),
//loockback
BottomNavigationBarItem(
icon: Icon(Icons.bar_chart,
color: _customColorScheme['Icon 1']),
activeIcon: Icon(Icons.bar_chart,
color: _customColorScheme['Icon 2']),
label: '',
),
//info & support
BottomNavigationBarItem(
icon: Icon(Icons.info, color: _customColorScheme['Icon 1']),
activeIcon:
Icon(Icons.info, color: _customColorScheme['Icon 2']),
label: '',
),
you can use like this like css break
final bottomNavHeight = getMyheight(context);
getMyheight(BuildContext context) {
var mheight = MediaQuery.of(context).size.height;
if (mheight < 300)
return mheight * 0.80;
else if (mheight < 400)
return mheight * 0.2;
else if (mheight < 500)
return mheight * 0.2;
else if (mheight < 600)
return mheight * 0.2;
else if (mheight < 800)
return mheight * 0.3;
else
return mheight * 0.085;
}
TIP
For Discrete jump i used windows run
NB: some packages dependent on platform so may exception so for ui testing it best discrete screen.
On Windows, desktop support is enabled on Flutter 2.10 or higher. On
macOS and Linux, desktop support is disabled by default in the stable
channel. You can manually enable it with one of these commands,
depending on which platform you are running:
flutter config --enable-macos-desktop
flutter config --enable-linux-desktop
flutter config --enable-windows-desktop
This package use to test different screen sizedevicepreview
device_preview: ^1.0.0
The bottom-overflow starts around <704. BottomNavigationBarItem's is not getting enough space.
You can remove SizedBox and just start with BottomNavigationBar, it will solve the issue.
bottomNavigationBar: BottomNavigationBar(....)

Don't show backbutton if index > 0

I have a scaffold and on the leading of AppBar a custom back button.
I have a int refIndex that initially is 0, but changes to the same value as the index of Pageview.builder changes
I want the backbuttnn to disappear if the refIndex > 0. I have no idea why its not working.
Widget leadingWiget() {
if (refIndex == 0) {
return IconButton(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
icon: const Icon(
Icons.chevron_left,
color: Colors.black,
size: 40,
),
onPressed: () {
// Navigator.of(context).pop();
print(refIndex);
},
);
}
return const SizedBox(height: 0, width: 0);
}
EDIT: I have the var declared right after the class class _QuestionsPageState extends State<QuestionsPage> {
in Pageview.builder, after itemBuilder: (ctx, index) { I have refIndex = index;
Is it wrong? I'm facing the same problem if I want to display the refIndex. The value itself changes when I change pages, but the displayed is the same as the initial, 0.
You can use the Visibilty Widget.
For example:
Visibilty(
visible: refIndex == 0,
child: IconButton(...),
)

How to randomly position widgets in a layout

Lets say I want to randomly position the widgets in a specific layout, like in the image attached below, how could I achieve it?
I was thinking of using a wrap widget, but that did not quit work, because it is not randomizing the children in a line. My code until now
return Wrap(
spacing: 30,
children: [
buildprofile(),
buildprofile(),
buildprofile(),
buildprofile(),
],
);
buildprofile() {
return Column(
children: [
CircleAvatar(
radius: 64,
backgroundColor: Colors.pink,
child: (CircleAvatar(
radius: 62,
backgroundImage: NetworkImage(profilepic),
)),
),
SizedBox(
height: 10,
),
Text(
"Sivaram",
style: mystyle(16, Colors.black, FontWeight.w700),
)
],
);
}
You could use flutter_staggered_grid_view
StaggeredGridView.count(
crossAxisCount: 4,
children: List.generate(
3,
(index) => Center(
child: CircleAvatar(
radius: 64,
backgroundColor: Colors.pink,
),
)),
staggeredTiles: [
StaggeredTile.count(2, 2), // takes up 2 rows and 2 columns space
StaggeredTile.count(2, 1), // takes up 2 rows and 1 column
StaggeredTile.count(1, 2), // takes up 1 row and 2 column space
], // scatter them randomly
);
You can create class Person, and store profile name and image,
class Person {
String name;
String imageUrl;
}
and in your code can store all your persons in array
List<Person> persons = [Person(), Person(),....]
Wrap(
spacing: 30,
children: _children
);
List<Widget> _children {
List<Widget> _widgets = List<Widget>();
List<Persons> _randomList = persons.shuffle();
_randomList.forEach((person) {
_widgets.add(_buildProfile(person))
});
return _widgets;
}