I have this simple code of NavigationRail
NavigationRail(
destinations: [
NavigationRailDestination(
icon: FaIcon(FontAwesomeIcons.list),
label: Text("Parkings"),
),
const NavigationRailDestination(
icon: FaIcon(FontAwesomeIcons.mapLocationDot),
label: Text("Map View"),
),
const NavigationRailDestination(
icon: FaIcon(FontAwesomeIcons.chartLine),
label: Text("Metrics"),
),
],
indicatorShape: CircleBorder(
// eccentricity: 0.8,
side: BorderSide(width: 1.0),
),
selectedIndex: 0,
),
this is the output of the above code? as you can see in the screenshot the indicator is so close to the icon is there any way to add padding/spacing in between them?
I have this simple code of NavigationRail
NavigationRail(
destinations: [
NavigationRailDestination(
icon: FaIcon(FontAwesomeIcons.list),
label: Text("Parkings"),
),
const NavigationRailDestination(
icon: FaIcon(FontAwesomeIcons.mapLocationDot),
label: Text("Map View"),
),
const NavigationRailDestination(
icon: FaIcon(FontAwesomeIcons.chartLine),
label: Text("Metrics"),
),
],
indicatorShape: CircleBorder(
// eccentricity: 0.8,
side: BorderSide(width: 1.0),
),
selectedIndex: 0,
),
this is the output of the above code? as you can see in the screenshot the indicator is so close to the icon is there any way to add padding/spacing in between them?
Share Improve this question edited Mar 11 at 10:29 Munsif Ali asked Mar 11 at 10:22 Munsif AliMunsif Ali 6,6155 gold badges25 silver badges55 bronze badges 3- Could you share the image of the required output? – DroidFlutter Commented Mar 11 at 11:27
- I don't have specific image but you can see in the screenshot the circle is very tight around the icon I want to add some in it. – Munsif Ali Commented Mar 12 at 4:22
- Have tried but not found for indicator padding. I have trick, you can use NavigationRailDestination (selectedIcon: Container(width: 60, height:60, child:Icon()) – DroidFlutter Commented Mar 12 at 7:05
2 Answers
Reset to default 0you can try in the below way where you can wrap "FaIcon" with padding.
NavigationRail(
destinations: [
NavigationRailDestination(
icon: Padding(
padding: const EdgeInsets.all(8.0), // Add padding to the icon
child: FaIcon(FontAwesomeIcons.list),
),
label: Text("Parkings"),
),
NavigationRailDestination(
icon: Padding(
padding: const EdgeInsets.all(8.0), // Add padding to the icon
child: FaIcon(FontAwesomeIcons.mapLocationDot),
),
label: Text("Map View"),
),
NavigationRailDestination(
icon: Padding(
padding: const EdgeInsets.all(8.0), // Add padding to the icon
child: FaIcon(FontAwesomeIcons.chartLine),
),
label: Text("Metrics"),
),
],
selectedIndex: 0,
indicatorShape: const CircleBorder(
side: BorderSide(width: 1.0, color: Colors.blue), // Customize the border
),
indicatorColor: Colors.blue.withOpacity(0.2), // Customize the indicator color
);
If you're still facing the same issue, I’ve built a CustomNavigationRail
for you.
=> Demo video for the provided Solution: CustomNavigationRail
Step 1: Create the Rail Model
The RailModel
class will hold the data for each navigation rail item, including the icon, label, and target widget the will shown when user select.
class RailModel {
final IconData icon;
final String label;
final Widget targetWidget;
const RailModel({
required this.icon,
required this.label,
required this.targetWidget,
});
}
Step 2: Build the DestinationWidget
This widget represents the main screen that will be displayed when a rail item is selected.
class DestenationWidget extends StatelessWidget {
const DestenationWidget({
super.key,
required this.text,
required this.color,
});
final String text;
final int color;
@override
Widget build(BuildContext context) {
return Container(
color: Color(color),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const FlutterLogo(
size: 150,
),
const SizedBox(height: 30),
Text(
text,
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
],
),
);
}
}
Step 3: Create the List<RailModel>
that will store the RailModel
items
This list stores all the navigation rail items using the RailModel
.
List<RailModel> railItems = const <RailModel>[
RailModel(
icon: Icons.list,
label: "List",
targetWidget: DestenationWidget(
text: "List Destiantion",
color: 0xFF80CBC4,
),
),
RailModel(
icon: Icons.map,
label: "Map",
targetWidget: DestenationWidget(
text: "Map Destiantion",
color: 0xFFFFD95F,
),
),
RailModel(
icon: Icons.stacked_bar_chart,
label: "Data",
targetWidget: DestenationWidget(
text: "Data Destiantion",
color: 0xFFE6B2BA,
),
),
];
Step 4: Build the Main Screen that will contain all the widget
class MyMainScreen extends StatelessWidget {
const MyMainScreen({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => RailManager(),
child: Consumer<RailManager>(
builder: (context, rail, _) {
return Scaffold(
body: Row(
children: <Widget>[
const CustomNavigationRail(
railWidth: 70.0,
),
Expanded(
child: railItems[rail.currentDestination].targetWidget,
),
],
),
);
},
),
);
}
}
Step 7: Create the provider that will manage the navigation
The RailManager
class manages the state of the selected destination using a ChangeNotifier
.
class RailManager with ChangeNotifier {
int currentDestination = 0;
void changeDestenation({required int target}) {
currentDestination = target;
notifyListeners();
}
}
Step 6: Build the CustomNavigationRail
Widget
class CustomNavigationRail extends StatelessWidget {
const CustomNavigationRail({
super.key,
this.railWidth = 60.0,
this.color = Colors.white,
this.borderRadius,
});
final double railWidth;
final Color color;
final BorderRadiusGeometry? borderRadius;
@override
Widget build(BuildContext context) {
return Consumer<RailManager>(
builder: (context, rail, _) {
return Container(
decoration: BoxDecoration(
color: color,
borderRadius: borderRadius,
),
width: railWidth,
child: Column(
children: <Widget>[
for (int i = 0; i < railItems.length; i++) ...{
NavigationRailItem(
icon: railItems[i].icon,
isSelected: i == rail.currentDestination,
label: railItems[i].label,
itemPadding: 8.0,
onTap: () {
rail.changeDestenation(target: i);
},
),
}
],
),
);
},
);
}
}
Step 7: Build the NavigationRailItem
Widget
class NavigationRailItem extends StatelessWidget {
const NavigationRailItem({
super.key,
required this.icon,
required this.isSelected,
required this.label,
required this.onTap,
this.itemPadding = 5.0,
});
final IconData icon;
final String label;
final bool isSelected;
final double itemPadding;
final void Function() onTap;
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Tooltip(
message: label,
child: Material(
color: Colors.transparent,
child: InkWell(
customBorder: const CircleBorder(),
onTap: onTap,
child: AnimatedContainer(
padding: EdgeInsets.all(itemPadding),
duration: const Duration(milliseconds: 300),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: isSelected ? const Color(0xFFEEEEEE) : null,
border: isSelected
? Border.all(color: Colors.grey, width: 2.0)
: null,
),
child: Icon(icon),
),
),
),
),
const SizedBox(height: 8.0),
if (isSelected) ...{
TweenAnimationBuilder(
tween: Tween<double>(begin: 10.0, end: 20),
duration: const Duration(milliseconds: 250),
builder: (context, width, child) {
return Container(
height: 3.0,
width: width,
decoration: BoxDecoration(
color: Colors.cyan,
borderRadius: BorderRadius.circular(5.0),
),
);
},
),
},
const SizedBox(height: 10),
],
);
}
}
The main property in this Solution is
itempadding
you can change the padding of the item as you want