最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

user interface - How to add padding or increase size of indicator in flutter NavigationRail? - Stack Overflow

programmeradmin5浏览0评论

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
Add a comment  | 

2 Answers 2

Reset to default 0

you 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

Hope that was Helpful !!

发布评论

评论列表(0)

  1. 暂无评论